NOIp 2017 奶酪 【并查集】 By cellur925
Orz去年考场上做这道题的我应该还在抱怨没学过空间几何,不一会太困了就开始打瞌睡,然后为了防止睡觉开始在devc++上写默写离骚(逃
思路:如果两个空洞相交,那么把他们并在一个集合里。最后对于每个集合,查看他们中是否同时存在与下表面相通和与上表面相通的空洞,存在则Yes.
细节:1 如何判断相交?类比平面中的概念,判断空间中两圆是否相交同样可以通过圆心间距离是否小于等于二倍半径来确定。
2 如何判断是否同时存在两个与下表面相通和与上表面相通的空洞?可以在输入的时候预处理出所有与下表面相通和与上表面相通的空洞,然后将他们进行枚举,如果存在在同一集合的情况则合法。
3 开long long!!!
Code
1 #include<cstdio> 2 #include<cmath> 3 #define maxn 1090 4 5 using namespace std; 6 typedef long long ll; 7 8 int T; 9 ll n,h,r,cnt,sum; 10 bool flag; 11 int fa[maxn],qaq[maxn],qwq[maxn]; 12 struct node{ 13 ll x,y; 14 ll z; 15 }point[maxn]; 16 17 int getf(int p) 18 { 19 if(fa[p]==p) return p; 20 else return getf(fa[p]); 21 } 22 23 void init() 24 { 25 cnt=0;sum=0;flag=0; 26 } 27 28 double dis(int l,int r) 29 { 30 return sqrt((point[l].x-point[r].x)*(point[l].x-point[r].x)+(point[l].y-point[r].y)*(point[l].y-point[r].y)+(point[l].z-point[r].z)*(point[l].z-point[r].z)); 31 } 32 33 int main() 34 { 35 scanf("%d",&T); 36 while(T--) 37 { 38 scanf("%lld%lld%lld",&n,&h,&r); 39 for(int i=1;i<=n;i++) 40 { 41 scanf("%lld%lld%lld",&point[i].x,&point[i].y,&point[i].z); 42 if(point[i].z-r<=0) qaq[++cnt]=i; 43 if(point[i].z+r>=h) qwq[++sum]=i; 44 } 45 for(int i=1;i<=n;i++) fa[i]=i; 46 for(int i=1;i<=n;i++) 47 for(int j=1;j<=n;j++) 48 { 49 if(i==j) continue; 50 if(dis(i,j)<=(double)2*r) 51 { 52 int pp=getf(i); 53 int qq=getf(j); 54 if(pp!=qq) 55 fa[qq]=pp; 56 } 57 } 58 for(int i=1;i<=cnt;i++) 59 { 60 for(int j=1;j<=sum;j++) 61 if(getf(qaq[i])==getf(qwq[j])) 62 { 63 printf("Yes\n"); 64 flag=1; 65 break; 66 } 67 if(flag) break; 68 } 69 if(!flag) printf("No\n"); 70 init(); 71 } 72 return 0; 73 }
小结:开始看题看的我一头雾水 T1难度都做不出
我还是太弱了。
独立意志与自由思想是必须争的,且须以生死力争。