【NOIP2017提高組Day 2】乳酪
阿新 • • 發佈:2021-01-26
技術標籤:題解
Description
現有一塊大乳酪,它的高度為 h,它的長度和寬度我們可以認為是無限大的,乳酪中間有許多 半徑相同 的球形空洞。我們可以在這塊乳酪中建立空間座標系,在座標系中,乳酪的下表面為z = 0,乳酪的上表面為z = h。
現在,乳酪的下表面有一隻小老鼠 Jerry,它知道乳酪中所有空洞的球心所在的座標。兩相切或是相交,則 Jerry 可以從其中一個空洞跑到另一個,特別地,如果一個空洞與下表面相切或是相交,Jerry 則可以從乳酪下表面跑進空洞;如果一個空洞與上表面相切或是相交,Jerry 則可以從空洞跑到乳酪上表面。
位於乳酪下表面的 Jerry 想知道,在 不破壞乳酪 的情況下,能否利用已有的空洞跑到乳酪的上表面去?
Input
每個輸入檔案包含多組資料。
輸入檔案的第一行,包含一個正整數 T,代表該輸入檔案中所含的資料組數。
接下來是 T 組資料,每組資料的格式如下:
第一行包含三個正整數 n,h 和 r,兩個數之間以一個空格分開,分別代表乳酪中空洞的數量,乳酪的高度和空洞的半徑。
接下來的 n 行,每行包含三個整數 x、y、z,兩個數之間以一個空格分開,表示空洞球心座標為(x,y,z)。
Output
輸出檔案包含 T 行,分別對應 T 組資料的答案,如果在第 i 組資料中,Jerry 能從下表面跑到上表面,則輸出“ Yes ”,如果不能,則輸出“ No ”(均不包含引號)。
solution
這道題我的方法是先預處理出那兩個點能夠互相到達,就是dist(P1,P2)小於2r,兩個點就可以互相到達,還要預處理出那些球能夠到達底面或者頂面,最後從底面DFS,如果能到達頂面,就輸出Yes,否則輸出No。
code
#include<bits/stdc++.h>
#define rg register int
using namespace std;
long long T,n,h,r,x[1005],y[1005],z[1005],f[1005][1005],bz[1005],ans;
int dist(int i,int j)
{
double s=sqrt((x[i]-x[j])*1.0*(x[i]-x[j])*1.0+(y[i]-y[j])*1.0*(y[i]-y[j])*1.0+(z[i]-z[j])*1.0*(z[i]-z[j])*1.0)*1.0;
if(s>(int)s) s++;
return s;
}
void dfs(int x)
{
if(x==n+1)
{
ans=1;
return;
}
bz[x]=1;
for(rg i=1;i<=n+1;i++)
if(f[x][i]&&(!bz[i]))
{
dfs(i);
if(ans==1) return;
}
}
int main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld%lld",&n,&h,&r),ans=0;
for(rg i=1;i<=n;i++) scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
for(rg i=0;i<=n;i++)
for(rg j=i+1;j<=n+1;j++) f[i][j]=f[j][i]=0;
for(rg i=1;i<=n;i++)
for(rg j=i+1;j<=n;j++)
if(dist(i,j)<=r*2) f[i][j]=f[j][i]=1;
for(rg i=1;i<=n;i++)
{
bz[i]=0;
if(h-z[i]<=r) f[i][n+1]=f[n+1][i]=1;
if(z[i]<=r) f[i][0]=f[0][i]=1;
}
dfs(0);
if(ans) printf("Yes\n");
else printf("No\n");
}
return 0;
}