zoukankan      html  css  js  c++  java
  • 洛谷P2526 【SHOI2001】小狗散步

    原题传送门

    题目背景

    Grant喜欢带着他的小狗Pandog散步。Grant以一定的速度沿着固定路线走,该路线可能自交。Pandog喜欢游览沿途的景点,不过会在给定的N个点和主人相遇。小狗和主人同时从(X1,Y1)点出发,并同时在(Xn,Yn)点汇合。小狗的速度最快是Grant的两倍。当主人从一个点以直线走向另一个点时,Pandog跑向一个它感兴趣的景点。Pandog每次与主人相遇之前最多只去一个景点。

    题目描述

    你现在的任务是:为Pandog寻找一条路线(有可能与主人的路线部分相同),使它能够游览最多的景点,并能够准时与主人在给定地点相遇或者汇合。

    输入输出格式

    输入格式:

    输入文件第一行是两个整数N和M( 1≤N,M≤100 );

    输入文件第二行的N个坐标给出了Grant的散步路线,即Pandog和主人相遇地点;

    输入文件第三行的M个坐标给出了所有Pandog感兴趣的景点。

    所有输入的坐标均不相同,且绝对值不超过1000。

    输出格式:

    输出小狗的移动路线。

    第一行是经过的点数,第二行依次为经过的点的坐标(直角坐标系)

    输入输出样例

    输入样例#1: 
    4 5
    1 4 5 7 5 2 -2 4
    -4 -2 3 9 1 2 -1 3 8 -3
    输出样例#1: 
    6
    1 4 3 9 5 7 5 2 1 2 -2 4

    题解

    前置知识二分图

    这道题是要求输出方案的二分图匹配问题的模板题,思维难度不高,代码简单。

    建模的方法很容易想到:

    我们将景点作为左集合的元素,将每两个集合点见的空隙作为右集合的元素,

    至于连边,我们只需要枚举每两个集合点见的空隙,再枚举每一个景点,如果来得及游玩就在两个点之间连边

    最终询问的结果就是N+最大匹配数。

    至于如何输出方案,只需要枚举并输出每一个集合点,如果该点与下一个点的空隙被匹配到了,就输出匹配到的景点

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int INF=1e9+7,MAXN=105,MAXM=MAXN*MAXN;
     5 struct node{
     6     int X,Y;
     7 }A[MAXN],B[MAXN];
     8 inline double dis(node x,node y){
     9     double ii=x.X-y.X,jj=x.Y-y.Y;
    10     return sqrt(ii*ii+jj*jj);
    11 }
    12 int N,M,ans;
    13 int head[MAXN],to[MAXM],nxt[MAXM],tp;
    14 inline void add(int x,int y){
    15     nxt[++tp]=head[x];
    16     head[x]=tp;
    17     to[tp]=y;
    18 }
    19 int used[MAXN],match[MAXN];
    20 bool dfs(int x){
    21     for(int i=head[x];i;i=nxt[i]){
    22         if(!used[to[i]]){
    23             used[to[i]]=1;
    24             if(!match[to[i]]||dfs(match[to[i]])){
    25                 match[to[i]]=x;
    26                 return 1;
    27             }
    28         }
    29     }
    30     return 0;
    31 }
    32 int main(){
    33     scanf("%d%d",&N,&M);
    34     for(int i=1;i<=N;i++){
    35         scanf("%d%d",&A[i].X,&A[i].Y);
    36     }
    37     for(int i=1;i<=M;i++){
    38         scanf("%d%d",&B[i].X,&B[i].Y);
    39     }
    40     for(int i=1;i<N;i++){
    41         for(int j=1;j<=M;j++){
    42             if(dis(A[i],A[i+1])*2.0>=dis(A[i],B[j])+dis(B[j],A[i+1])){
    43                 add(j,i);
    44             }
    45         }
    46     }
    47     for(int i=1;i<=M;i++){
    48         memset(used,0,sizeof(used));
    49         ans+=dfs(i);
    50     }
    51     printf("%d
    ",ans+N);
    52     for(int i=1;i<=N;i++){
    53         printf("%d %d ",A[i].X,A[i].Y);
    54         if(match[i]){
    55             printf("%d %d ",B[match[i]].X,B[match[i]].Y);
    56         }
    57     }
    58     return 0;
    59 }
  • 相关阅读:
    【题解】 bzoj1191: [HNOI2006]超级英雄Hero (二分图)
    谈谈Android项目框架的前世今生
    十四个好用的开源漏洞检测工具
    关于Java导出100万行数据到Excel的优化方案
    逗号分割符--字段中含逗号等情况的解析方法Java实现
    Java日期处理
    服务器&浏览器伪装的故事
    浏览器User-agent简史(user-agent)
    修改tomcat服务器banner的方法
    life_motto
  • 原文地址:https://www.cnblogs.com/guoshaoyang/p/10567138.html
Copyright © 2011-2022 走看看