luogu 3958 奶酪
noip2017 D2T1 奶酪 某zz选手没有想到可以用并查集来做,直接用了dijskstra,结果被ccf老爷机卡成了70分
题目大意:
现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多半径相同的球形空洞
我们可以在这块奶酪中建立空间坐标系,在坐标系中, 奶酪的下表面为z=0,奶酪的上表面为 z=h。
现在,知道奶酪中所有空洞的球心所在的坐标,起点为奶酪的下表面 如果两个空洞相切或是相交,则可以从其中一个空洞跑到另一个空洞
特别地,如果一个空洞与下表面相切或是相交,则可以从奶酪下表面跑进空洞;如果一个空洞与上表面相切或是相交,则可以从空洞跑到奶酪上表面。
位于奶酪下表面的 Jerry 想知道,在 不破坏奶酪 的情况下,能否利用已有的空洞跑 到奶酪的上表面去?
空间内两点P1(x1,y1,z1)、P2(x2,y2,z2)的距离公式如下:
dist(P1,P2)=sqrt((x1−x2)2+(y1−y2)2+(z1−z2)^2)
思路:
随便用并查集或dij或spfa来做,判断上下表面是否连通即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cstring> 7 #include<queue> 8 #include<map> 9 #include<vector> 10 #define inf 2147483611 11 #define ll long long 12 #define MAXN 1010 13 #define P pair<int,int> 14 #define mp(a,b) make_pair(a,b) 15 using namespace std; 16 inline int read() 17 { 18 int x=0,f=1;char ch=getchar(); 19 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 20 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 21 return x*f; 22 } 23 struct node {double x,y,z;}a[MAXN]; 24 double dist(node a,node b) 25 { 26 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)); 27 } 28 int T,n,h,r,nxt[MAXN*MAXN],fst[MAXN],to[MAXN*MAXN],cnt,dis[MAXN]; 29 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} 30 void dij() 31 { 32 priority_queue<P,vector<P>,greater<P> > q; 33 q.push(mp(0,n+1));memset(dis,127,sizeof(dis));dis[n+1]=0; 34 while(!q.empty()) 35 { 36 int k=q.top().second;q.pop(); 37 for(int i=fst[k];i;i=nxt[i]) 38 { 39 if(dis[to[i]]>dis[k]+1) {dis[to[i]]=dis[k]+1;q.push(mp(dis[to[i]],to[i]));} 40 } 41 if(dis[n+2]!=2139062143) break; 42 } 43 if(dis[n+2]!=2139062143) puts("Yes"); 44 else puts("No"); 45 } 46 int main() 47 { 48 //freopen("cheese.in","r",stdin); 49 //freopen("cheese.out","w",stdout); 50 T=read(); 51 while(T--) 52 { 53 memset(nxt,0,sizeof(nxt)); 54 memset(fst,0,sizeof(fst)); 55 n=read(),h=read(),r=read(); 56 for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z); 57 for(int i=1;i<=n;i++) 58 { 59 if(a[i].z<=r) add(n+1,i); 60 if(a[i].z+r>=h) add(i,n+2); 61 for(int j=1;j<=n;j++) 62 { 63 if(i==j) continue; 64 if(dist(a[i],a[j])<=2*r) {add(i,j);add(j,i);} 65 } 66 } 67 dij(); 68 } 69 }