1. 程式人生 > 其它 >【NOIP2017提高組Day 2】乳酪

【NOIP2017提高組Day 2】乳酪

技術標籤:題解

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; }