計蒜客 奶酪 (並查集)
阿新 • • 發佈:2017-11-23
long con print 知識 sca clas 之間 mark author
鏈接 : Here!
思路 :
- 其實這個是一道簡單的並查集問題, 判斷$Jerry$是否能從下表面跑到上表面, 其實質上是判斷上表面和下表面是否連通, 因此這道問題就變成了判斷連通性的問題了. 判斷標準是如果$d <= 2 * r$ ($d$為兩球心之間的距離), 那麽就合並兩個集合即可
思考 : 將知識穿成線索,做等價遷移,將復雜問題變成簡單問題.
代碼 :
/*************************************************************************
> File Name: t13.cpp
> Author:
> Mail:
> Created Time: 2017年11月21日 星期二 16時33分31秒
************************************************************************/
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
#define MAX_N 1010
typedef long long ll;
int par[MAX_N];
int size[MAX_N];
ll n, h, r;
struct Point {
ll x, y, z;
};
double check(Point a, Point b) {
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)) <= 2 * r);
}
void init() {
for (int i = 0 ; i < MAX_N ; ++i) {
par[i] = i;
size[i] = 1 ;
}
}
int find(int x) {
return x == par[x] ? x : (par[x] = find(par[x]));
}
void merge(int x, int y) {
x = find(x);
y = find(y);
if (x == y) return;
if (size[x] > size[y]) {
size[x] += size[y];
par[y] = x;
} else {
size[y] += size[x];
par[x] = y;
}
}
int same(int x, int y) {
return find(x) == find(y);
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
init();
Point data[MAX_N];
scanf("%lld%lld%lld", &n, &h, &r);
for (int i = 2 ; i <= n + 1 ; ++i) {
scanf("%lld%lld%lld", &data[i].x, &data[i].y, &data[i].z);
}
// 先把能接觸到地面的點加入到地面集合0中
for (int i = 2 ; i <= n + 1 ; ++i) {
if (fabs(0 - data[i].z) > r) continue;
if (same(0, i)) continue;
merge(0, i);
}
// 再把能接觸到上端的點加入到頂端集合1中
for (int i = 2 ; i <= n + 1 ; ++i) {
if (fabs(h - data[i].z) > r) continue;
if (same(1, i)) continue;
merge(1, i);
}
for (int i = 2 ; i <= n + 1 ; ++i) {
for (int j = 2 ; j <= n + 1 ; ++j) {
if (same(i, j)) continue;
if (!check(data[i], data[j])) continue;
merge(i, j);
}
}
if (same(0, 1)) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
}
計蒜客 奶酪 (並查集)