这个题是2017noip提高组的真题,是一个深度搜索题,得分轨迹:10-80-100pts。
在三维空间里,存在可能连通的洞(半径r),问是否可以通过这些洞从底部到达顶部。一开始我联想到了01迷宫,以联通块的方式求解,但发现不可。于是就单纯想用一个一维的dfs去枚举,发现这个dfs的时间复杂度很低,似乎每一个节点访问一遍即可。首先确定了每次要枚举的是当前的坐标,如果z+r>=h则flag=true,如果没有就for(1~n),打上标记,但在这里,每一个点只需要走一次就可以了,因为从2-4如果到不了,那么从3-4也到不了,所以不用回溯。但是需要有一个入口,那么要把dfs放到一个for里,如果z<=r,那么进去。但是对于数据类型的定义我出现了问题,请教了lz,hhs,lxy大佬。
1.要想骗到分或者代码写崩了,仔细看数据范围,比如这个题n=1,直接判断能不能到达底部和顶部就20分了。
2.多组数据输出时别忘了换行。
3.计算公式的正确性一定要保证,调试的时候心态放平,按部就班,应该可以找出来的。
4.对于数据的类型定义,sqrt要double,平方要long long这些都要想清楚
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 struct node{ 9 double x; 10 double y; 11 double z; 12 }a[1000005]; 13 int book[1000005]; 14 int T; 15 int n,h; 16 long long r; 17 bool flag=false; 18 long long d; 19 long long dis(double x,double y,double z,double xx,double yy,double zz){ 20 return ((x-xx)*(x-xx)+(y-yy)*(y-yy)+(z-zz)*(z-zz)); 21 // return ((x-xx)^2+(y-yy)^2+(z-zz)^2); 22 } 23 void dfs(double x,double y,double z){ 24 if(z+r>=h){ 25 flag=true; 26 return; 27 } 28 if(flag==false){ 29 for(int i=1;i<=n;i++){ 30 if(book[i]==0){ 31 //cout<<dis(x,y,z,a[i].x,a[i].y,a[i].z); 32 if(dis(x,y,z,a[i].x,a[i].y,a[i].z)<=r*r*4){//相交或相切 33 book[i]=1; 34 dfs(a[i].x,a[i].y,a[i].z); 35 //cout<<i<<endl; 36 } 37 } 38 else continue; 39 } 40 } 41 } 42 int main(){ 43 scanf("%d",&T); 44 for(int i=1;i<=T;i++){ 45 flag=false; 46 cin>>n>>h>>r; 47 for(int i=1;i<=n;i++){ 48 cin>>a[i].x>>a[i].y>>a[i].z; 49 book[i]=0; 50 } 51 for(int i=1;i<=n;i++){ 52 if(flag==true) break; 53 if(a[i].z<=r){ 54 // cout<<i<<endl; 55 book[i]=1; 56 dfs(a[i].x,a[i].y,a[i].z); 57 } 58 } 59 if(flag==true) cout<<"Yes"<<endl; 60 else cout<<"No"<<endl; 61 } 62 return 0; 63 }