洛谷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 }
原文地址:https://www.cnblogs.com/guoshaoyang/p/10567138.html