NOIP2017 D2T1 奶酪

洛谷P3958

 

超级水的并没有用什么几何知识的几何题……

直接爆搜一遍最后判断有没有与上/下表面相连的球之间连通即可……O(n2)不动脑子的复杂度

最多只是用一下并查集来判断两个点是否连通……

 

具体细节不必赘述代码如下(超简洁只有51行)

 1 #include<cstdio>
 2 #include<cmath>
 3 using namespace std;
 4 struct ball
 5 {
 6     long long x,y,z;//开成long long防止运算溢出 
 7 }balls[1001];//存储球心信息 
 8 int up[1001],down[1001],tot1,tot2;//和上表面/下表面接触的球的球心编号及数组的大小标记 
 9 int fa[1001];//并查集组件 
10 int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}//寻找父亲 
11 double dis(ball i,ball j){return sqrt((i.x-j.x)*(i.x-j.x)+(i.y-j.y)*(i.y-j.y)+(i.z-j.z)*(i.z-j.z));}//求球心矩 
12 int main()
13 {
14     int t;
15     scanf("%d",&t);
16     while(t--)
17     {
18         for(int i=1;i<=1000;i++)
19             fa[i]=i;//初始化fa数组 
20         tot1=tot2=0;
21         int n,h,r;
22         scanf("%d%d%d",&n,&h,&r);
23         for(int i=1;i<=n;i++)
24         {
25             int x,y,z;
26             scanf("%d%d%d",&x,&y,&z);
27             balls[i].x=x;balls[i].y=y;balls[i].z=z;
28             if(z+r>=h)//球与上表面相交 
29                 up[++tot1]=i;
30             if(z-r<=0)//球与下表面相交 
31                 down[++tot2]=i;
32         }
33         for(int i=1;i<=n;i++)//判断任意两个球是否相交 
34             for(int j=i+1;j<=n;j++)
35                 if(dis(balls[i],balls[j])<=2*r)
36                     fa[getfa(i)]=getfa(j);//若相交,合并 
37         bool ans=false;
38         for(int i=1;i<=tot1;i++)
39             for(int j=1;j<=tot2;j++)
40                 if(getfa(up[i])==getfa(down[j]))//如果从上面与下面相通,则为真 
41                 {
42                     ans=true;
43                     break;
44                 }
45         if(ans)
46             printf("Yes\n");
47         else
48             printf("No\n");
49     }
50     return 0;
51 }

 我只想提醒一点……判断球是否与上下表面相邻(读入处理的地方)一定一定不要加else!因为一个球可能同时与上下表面相连!我随手加个else30分就没有了………………

posted @ 2018-08-17 22:39  李昊哲  阅读(167)  评论(0编辑  收藏  举报