题意:主人带狗去散步,主人走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 }