题意:主人带狗去散步,主人走n个点,狗在每个点都会与主人碰头,但其余时候都是各自溜达,除此之外,狗还会去找一些有趣的地方(共m个),每次离开主人狗最多去一个有趣的地方。狗的速度最快是人的两倍,求使得狗到达最多有趣点的方法。

题解:对于人从第i个点到第i+1个点,这条路作为三角形的一边c,然后遍历其他点,若j与这两个点组成的边即为a,b如果a+b<=c则g[i][j]=true,然后做二分图最大匹配,就是狗最多能到的点。

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 const double eps=1e-8;
 7 bool chk[120],g[120][120];
 8 int n,m,xm[120],ym[120];
 9 bool findpath(int x)
10 {
11     for(int y=0;y<m;y++)
12     {
13         if(g[x][y]&&!chk[y])
14         {
15             chk[y]=true;
16             if(ym[y]==-1||findpath(ym[y]))
17             {
18                 xm[x]=y;
19                 ym[y]=x;
20                 return true;
21             }
22         }
23     }
24     return false;
25 }
26 int maxmatch()
27 {
28     memset(xm,-1,sizeof(xm));
29     memset(ym,-1,sizeof(ym));
30     int ret=0;
31     for(int i=0;i<n;i++)
32     {
33         memset(chk,false,sizeof(chk));
34         if(findpath(i))
35             ret++;
36     }
37     return ret;
38 }
39 int po[120][2],so[120][2];
40 double cal(int x1,int y1,int x2,int y2)
41 {
42     return sqrt((double)((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
43 }
44 bool check(int i,int j,int k)
45 {
46     double a,b,c;
47     a=cal(po[i][0],po[i][1],so[k][0],so[k][1]);
48     b=cal(po[j][0],po[j][1],so[k][0],so[k][1]);
49     c=cal(po[i][0],po[i][1],po[j][0],po[j][1]);
50     if(a+b<2.0*c+eps)
51         return true;
52     else
53         return false;
54 }
55 int main()
56 {
57     int nn;
58     while(scanf("%d%d",&nn,&m)!=EOF)
59     {
60         memset(g,false,sizeof(g));
61         for(int i=0;i<nn;i++)
62             scanf("%d%d",&po[i][0],&po[i][1]);
63         for(int i=0;i<m;i++)
64             scanf("%d%d",&so[i][0],&so[i][1]);
65         n=nn-1;
66         for(int i=0;i<n;i++)
67         {
68             for(int j=0;j<m;j++)
69                 if(check(i,i+1,j))
70                     g[i][j]=true;
71         }
72         printf("%d\n",nn+maxmatch());
73         for(int i=0;i<n;i++)
74         {
75             printf("%d %d ",po[i][0],po[i][1]);
76             if(xm[i]!=-1)
77                 printf("%d %d ",so[xm[i]][0],so[xm[i]][1]);
78         }
79         printf("%d %d\n",po[n][0],po[n][1]);
80     }
81     return 0;
82 }