acwing 528. 奶酪 解題記錄

習題地址 https://www.acwing.com/problem/content/description/530/node

現有一塊大奶酪,它的高度爲h,它的長度和寬度咱們能夠認爲是無限大的,奶酪中間有許多半徑相同的球形空洞。ios

咱們能夠在這塊奶酪中創建空間座標系,在座標系中,奶酪的下表面爲z=0,奶酪的上表面爲z=h。 nginx

如今,奶酪的下表面有一隻小老鼠Jerry,它知道奶酪中全部空洞的球心所在的座標。ide

若是兩個空洞相切或是相交,則Jerry能夠從其中一個空洞跑到另外一個空洞,特別地,若是一個空洞與下表面相切或是相交,Jerry則能夠從奶酪下表面跑進空洞;若是一個空洞與上表面相切或是相交,Jerry則能夠從空洞跑到奶酪上表面。atom

位於奶酪下表面的Jerry想知道,在不破壞奶酪的狀況下,可否利用已有的空洞跑到奶酪的上表面去? spa

空間內兩點P1(x1,y1,z1)P2(x2,y2,z2)𝑃1(𝑥1,𝑦1,𝑧1)、𝑃2(𝑥2,𝑦2,𝑧2)的距離公式以下:3d

輸入格式

每一個輸入文件包含多組數據。  code

輸入文件的第一行,包含一個正整數T,表明該輸入文件中所含的數據組數。  xml

接下來是T組數據,每組數據的格式以下:blog

第一行包含三個正整數n,h和r,兩個數之間以一個空格分開,分別表明奶酪中空洞的數量,奶酪的高度和空洞的半徑。  

接下來的n行,每行包含三個整數x、y、z,兩個數之間以一個空格分開,表示空洞球心座標爲(𝑥,𝑦,𝑧)。

輸出格式

輸出文件包含T行,分別對應T組數據的答案,若是在第i組數據中,Jerry能從下表面跑到上表面,則輸出「Yes」,若是不能,則輸出「No」(均不包含引號)。

數據範圍

1n10001≤n≤1000,
1h,r1091≤h,r≤109,
T20T≤20,
座標的絕對值不超過109109

輸入樣例:

3 
2 4 1 
0 0 1 
0 0 3 
2 5 1 
0 0 1 
0 0 4 
2 5 2 
0 0 2 
2 0 4

輸出樣例:

Yes No Yes

 

一種直接搜索 剪枝,一種使用能聯通的孔記錄並查集,尋找聯通上下層的孔是否在一個集合


解法1 BFS搜索

 1 #include <iostream>
 2 #include <queue>
 3 #include <memory.h>
 4 #include <math.h>       /* sqrt */
 5 
 6 using namespace std;
 7 
 8 
 9 struct node{
10     double x,y,z;
11 };
12 
13 const int N = 1010;
14 node a[N];
15 int vis[N],n,h,r,t;
16 queue<node> q;
17 
18 double distance(node a,node b)
19 {
20     double nx = a.x-b.x,ny = a.y-b.y,nz = a.z-b.z;
21     double ans = sqrt(nx*nx+ny*ny+nz*nz);
22     return ans;
23 }
24 
25 int bfs()
26 {
27     while(!q.empty()){
28         if(q.front().z+r >= h)
29             return 1;
30         node currentNode = q.front();
31         q.pop();
32         //計算該點和其餘點是否能夠鏈接走動
33         for(int i = 1;i <= n;i++){
34             if( ( 2*r >= distance(currentNode,a[i]) )  && vis[i] != 1 ){
35                 q.push(a[i]);
36                 vis[i] =1;
37                 if(q.front().z+r >= h)
38                     return 1;
39             }
40         }
41     }
42     
43     return 0;
44 }
45 
46 
47 int main()
48 {
49     cin >> t;
50     
51     while(t--){
52        
53         cin >> n >> h >> r;
54         
55         //初始化
56         q = queue<node>();
57         memset(vis,0,sizeof(vis));
58         
59         for(int i = 1;i <= n;i++){
60             cin >> a[i].x >> a[i].y>>a[i].z;
61             if(a[i].z  <=  r){
62                 q.push(a[i]);
63                 vis[i] = 1;
64             }
65         }
66         
67         if(bfs()){
68             cout << "Yes" << endl;
69         }else{
70             cout << "No"<<endl;
71         }
72         
73     }
74     
75     
76     return 0;
77 }
View Code

 

 

解法2  並查集

 1 #include <cstdio>
 2 #include <vector>
 3 #include <cstdlib>
 4 
 5 using namespace std;
 6 
 7 struct point{
 8     long long x,y,z;
 9     void write(int a,int b,int c){x= a;y = b;z= c;}
10 };
11 point pts[1001];
12 unsigned long long h,r,n; int T;
13 unsigned long long disSqu(int a,int b){
14     unsigned long long res = (pts[a].x-pts[b].x)*(pts[a].x-pts[b].x) +
15         (pts[a].y-pts[b].y)*(pts[a].y-pts[b].y) + (pts[a].z-pts[b].z)*(pts[a].z-pts[b].z);
16     return res;
17 }
18 
19 int parent[1001];
20 void init(){
21     for(int i = 1;i <=n;i++)
22         parent[i] = i;
23 }
24 
25 int find(int cu){
26     return parent[cu] == cu? cu:parent[cu] = find(parent[cu]); 
27 }
28 
29 void merge(int a,int b)
30 {
31     int x = find(a),y = find(b);
32     if(x < y) parent[y] = x;
33     else parent[x] = y;
34 }
35 
36 vector<int> but,top;
37 
38 int main()
39 {
40     vector<int>::iterator it1,it2;
41     bool flag;
42     unsigned long long lim;long long a,b,c;
43     scanf("%d",&T);
44     for(int z = 1;z <= T;z++){
45         scanf("%lld %lld %lld",&n,&h,&r);
46         but.clear();top.clear();init();flag = false;
47         lim = r*r*4;
48         for(int i = 1;i <= n; i++){
49             scanf("%lld %lld %lld",&a,&b,&c);
50             pts[i].write(a,b,c);
51             if(c<=r){but.push_back(i);}
52             if(c>=h-r){top.push_back(i);}
53         }
54         if(h <= r) { printf("Yes\n");continue; }
55         for(int i = 1;i <= n;i++){
56             for(int j = i+1;j <= n;j++){
57                 if(disSqu(i,j) <= lim) merge(i,j);
58             }
59         }
60         
61         for(it1 = top.begin();it1 != top.end();it1++){
62             for(it2 = but.begin();it2 != but.end();it2++){
63                 if(find(*it1) == find(*it2)){
64                     printf("Yes\n");
65                     flag= true;
66                     break;
67                 }
68             }
69             if(flag) break;
70         }
71         
72         if(!flag) printf("No\n");
73     }
74     
75     return 0;
76 }
View Code
相關文章
相關標籤/搜索