链接: 原题链接
输入输出样例
输入 #1
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
输出 #1
Yes
No
Yes
思路讲解
本題是一个简单的DFS/BFS搜索问题,也可以用并查集来做。
下面讲解一下DFS思路。
首先,奶酪上的洞个数是不确定的,并且输入的洞的位置(主要是高低)不是有序的,因此要先根据高度对洞进行排序。
DFS中要判断两个洞是否相连,即两洞之间距离是否小于等于球直径(注意是直径)。难点在于如何判断是否可以穿过奶酪。只有从下表面通过一个个相连的洞然后穿过与上表面相连的洞才能穿过奶酪。从最下面的一个洞开始走,走过的洞标记已经走过,凡是走过的洞都不再走,但如果前方不能再走了还返回这个洞,寻找下一个能连接到此洞的洞,这样的话就可以将每一个能和底边连接到的洞全部判断一遍,只要其中有洞连接到顶端,就用flag记录为1。再进行适当的剪枝!
注意:与底边相连的洞可能有很多,应该从每一个与底边相连的洞开始DFS一遍,直到有穿过奶酪的路径为止。因此在主函数中我们用循环把能连接到底边的所有洞DFS一遍即可。
代码实现
DFS:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
int t;
long long n,h,r; //注意变量类型要开 long long
struct node{
long long x,y,z;
}yuan[MAXN];
int v[MAXN];
bool cmp(node a,node b)
{
return a.z<b.z;
}
int flag;
void DFS(int a); //当前要判断的洞
int main()
{
scanf("%d",&t);
while(t--)
{
flag=0;
memset(v,0,sizeof(v));// 因为有多组数据,所以每次都要初始化
scanf("%ld%ld%ld",&n,&h,&r);
for(int i=1;i<=n;i++)
scanf("%ld%ld%ld",&yuan[i].x,&yuan[i].y,&yuan[i].z);
sort(yuan+1,yuan+1+n,cmp);
for(int i=1;i<=n;i++)
{
if(flag==1)break; // 剪枝
if(v[i]==0&&yuan[i].z<=r)
{
v[i]=1;
DFS(i);
}
}
if(flag)printf("Yes\n");
else printf("No\n");
}
}
void DFS(int a)
{
if(yuan[a].z+r>=h)
{
flag=1;
return;
}
for(int i=a+1;i<=n;i++)
{
if(flag==1)return; //剪枝
long long tx,ty,tz,as;
tx=(yuan[i].x-yuan[a].x)*(yuan[i].x-yuan[a].x);
ty=(yuan[i].y-yuan[a].y)*(yuan[i].y-yuan[a].y);
tz=(yuan[i].z-yuan[a].z)*(yuan[i].z-yuan[a].z);
as=tx+ty+tz; //距离的平方
long long dis=2*r;
if(v[i]==0&&as<=dis*dis)//
{
v[i]=1;
DFS(i);
v[i]=0;
}
}
}
BFS:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
int t;
long long n,h,r;
int flag;
int v[MAXN];
struct node{
long long x,y,z;
}yuan[MAXN],start,temp;
bool cmp(node a,node b)
{
return a.z<b.z;
}
int dis(node a,node b)
{
long long tyx,tyy,tyz,as;
tyx=a.x-b.x;
tyy=a.y-b.y;
tyz=a.z-b.z;
as=tyx*tyx+tyy*tyy+tyz*tyz;
if(as>2*r*2*r) return 0;
else return 1;
}
queue<node>d;
void BFS(int a);//从第几号开始判断
int main()
{
scanf("%d",&t);
while(t--)
{
flag=0;
memset(v,0,sizeof(v));
scanf("%ld%ld%ld",&n,&h,&r);
for(int i=1;i<=n;i++)
scanf("%ld%ld%ld",&yuan[i].x,&yuan[i].y,&yuan[i].z);
sort(yuan+1,yuan+1+n,cmp);
for(int i=1;i<=n;i++)
if(v[i]==0&&yuan[i].z<=r)
{
if(flag==1)break;
v[i]=1;
BFS(i);
}
if(flag)printf("Yes\n");
else printf("No\n");
}
}
void BFS(int a)//从第几号开始判断
{
d=queue<node>();//清空队列
start=yuan[a];
d.push(start);
while(!d.empty())
{
temp=d.front();
if(temp.z+r>=h)
{
flag=1; //只要有一种路径穿过奶酪就标记
break; //退出
}
for(int k=a+1;k<=n;k++)
{
if(v[k]==0&&dis(yuan[k],temp))
{
v[k]=1;
d.push(yuan[k]);
}
}
d.pop();
}
}
继续加油!