uva 11853 paintball(好题)——yhx
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 struct circ 5 { 6 double x,y,r; 7 }a[1010]; 8 bool vis[1010]; 9 int n; 10 double ans_l,ans_r; 11 double min(double a,double b) 12 { 13 return a<b?a:b; 14 } 15 bool conn(int x,int y) 16 { 17 double dis=sqrt((a[x].x-a[y].x)*(a[x].x-a[y].x)+(a[x].y-a[y].y)*(a[x].y-a[y].y)); 18 if (dis<=a[x].r+a[y].r) return 1; 19 return 0; 20 } 21 bool dfs(int x) 22 { 23 int i; 24 vis[x]=1; 25 if (a[x].y-a[x].r<=0) return 1; 26 if (a[x].x-a[x].r<=0) 27 ans_l=min(ans_l,a[x].y-sqrt(a[x].r*a[x].r-a[x].x*a[x].x)); 28 if (a[x].x+a[x].r>=1000) 29 ans_r=min(ans_r,a[x].y-sqrt(a[x].r*a[x].r-(1000-a[x].x)*(1000-a[x].x))); 30 for (i=1;i<=n;i++) 31 if (vis[i]==0&&conn(x,i)) 32 if (dfs(i)) return 1; 33 return 0; 34 } 35 int main() 36 { 37 int i,j,k,m,p,q,x,y,z; 38 bool b; 39 while (scanf("%d",&n)==1) 40 { 41 ans_l=ans_r=1000; 42 memset(a,0,sizeof(a)); 43 memset(vis,0,sizeof(vis)); 44 for (i=1;i<=n;i++) 45 scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].r); 46 b=0; 47 for (i=1;i<=n;i++) 48 if (vis[i]==0&&a[i].y+a[i].r>=1000&&dfs(i)) 49 { 50 printf("IMPOSSIBLE\n"); 51 b=1; 52 break; 53 } 54 if (b==0) printf("0.00 %.2lf 1000.00 %.2lf\n",ans_l,ans_r); 55 } 56 }
题意需要几步转化。
关键要自己手画几个图感受一下。
避免攻击离开战场
→1.以敌人为障碍物,找到一条从左到右的通路。
→2.以敌人为路,找到一条从上到下的通路。(如果有一条上下贯通的路,则一定把地图分为左右两部分,即不存在左右通路。)
从每个与上边界相交或相切的圆开始搜索和它相交或相切的圆。如果搜到一个和下边界相交或相切的圆,则判定impossible。
于是判定就解决了。
求解可以与判定同时进行,每搜索到一个圆,就看他是否与左右边相交或相切,如果是的话那交点以上的部分就被困在角上(因为如果搜索到了这个圆,那他一定直接或间接连到了上边界),需要用它的靠下的交点更新答案。