noip2017 Day2 T1——cheese

说一道题水,要么是它真的水,要么是你还没有用代码实现过它----Jerry
noip2017 Day2 T1——cheese_第1张图片

题目:

分析:

把其抽象为一个图,则这个图起点应该是那个可能存在的与h=0平面有交点的点,终点应该就是那个可能存在的和奶酪上表面有相交的那个点。于是,方式一的思路就是,建图+染色爆搜

但其实我们发现,如果我们知道所有与上表面相交的圆的标号和与下表面相交的圆的标号,那么我们只需要判断这两种圆是否存在相连关系即可。涉及到集合的合并与查询,我们考虑并查集(方式2)

代码实现

毕竟只是T1,思维难度不大,但一不小心就会掉入坑

下面总结一下这道题的坑点
1.数据范围与精度:注意避免开根运算,且注意两倍半径的平方超过了INT_MAX,若要写快读,请注意负数的存在
2.思路:思路明确,不可方案一和方案二混用可能只有我这种蒟蒻才会有这种问题吧
3.其他:注意输出,不能把“Yes”打成“YES”等,注意多组数据的数据初始化(反正我是用类来实现的)

code:(dfs爆搜)

#include
using namespace std;
long long numOFdata,numOFspot,height,radius;
struct position{int x;int y;int z;};
position holl[1000+5];
int used[1000+5];
int bottom[100+5],bottomCNT=0;
bool success;
void run();
void init()
{
    //freopen("datain.txt","r",stdin);
    
}
void datasetting()
{
    scanf("%lld",&numOFdata);
    for(int i=0;i<numOFdata;i++)
    {
        success=false;
        memset(used,0,sizeof(used));
        memset(bottom,0,sizeof(bottom));
        bottomCNT=0;
        scanf("%lld%lld%lld",&numOFspot,&height,&radius);
        for(int i=0;i<numOFspot;i++)
        {
            scanf("%d%d%d",&holl[i].x,&holl[i].y,&holl[i].z);
            if(holl[i].z<=radius)
            {
                bottomCNT++;
                bottom[bottomCNT]=i;
            }
        }
        run();
    }
}
bool check(position a,position b)
{
    long long x1=a.x-b.x,x2=a.y-b.y,x3=a.z-b.z;
    if(x1*x1+x2*x2+x3*x3<=2*radius*2*radius)return true;
    else return false;
}
void dfs(position now,int nowheight)
{
    if(success)return;
    if(nowheight+radius>=height)
    {
        success=true;
        return;
    }
    for(int i=0;i<numOFspot;i++)
    {
        if(used[i]==1)continue;
        if(check(holl[i],now)==false)continue;
        used[i]=1;
        dfs(holl[i],holl[i].z);
    }
}
void run()
{
    if(bottomCNT==0)
    {
        printf("No\n");
        return;
    }
    for(int i=1;i<=bottomCNT;i++)
    {
        position inholl;
        inholl=holl[bottom[i]];
        used[bottom[i]]=1;
        dfs(inholl,inholl.z);
        if(success)
        {
            printf("Yes\n");
            return;
        }
    }
    printf("No\n");
}
int main()
{
    init();
    datasetting();
    return 0;
}

code(方案2)

#include
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;i++)
#define clean(arry,num); memset(arry,num,sizeof(arry));
#define ll long long
const int maxn=1050;
struct node{ll x;ll y;ll z;};
class dfs
{
	public:
		int n;int h;ll r;
		node data[maxn];
		int fa[maxn];
		bool up[maxn],down[maxn];
		inline ll read()
		{	
			ll ans=0;char r=getchar();bool neg=false;
			while(r>'9'||r<'0'){if(r=='-')neg=true;r=getchar();}
			while(r>='0'&&r<='9'){ans=ans*10+r-'0';r=getchar();}
			return (neg==false)?ans:-ans;
		}
		int findf(int u){return fa[u]=((fa[u]==u)?u:findf(fa[u]));}
		bool c_con(node x,node y)
		{
			long long dis=(x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y)+(x.z-y.z)*(x.z-y.z);
			return ((dis<=(long long)(4*r*r))?true:false);
		}
		void datasetting()
		{
			n=read();h=read();r=read();clean(up,false);clean(down,false);
			loop(i,0,n-1)fa[i]=i;
			loop(i,0,n-1)
			{
				ll x,y,z;x=read();y=read();z=read();
				data[i].x=x;data[i].y=y;data[i].z=z;
				if(data[i].z<=r)down[i]=true;
				if(h-data[i].z<=r)up[i]=true;
				loop(j,0,i-1)if(c_con(data[i],data[j])){fa[findf(j)]=i;}
		void work()
		{
			datasetting();
			loop(i,0,n-1)
			{
				if(!down[i])continue;
				loop(j,0,n-1)
				{
					if(!up[j])continue;
					if(findf(i)==findf(j)){printf("Yes\n");return;}
				}
			}
			printf("No\n");
		}
}fun;
int main()
{
	//freopen("datain.txt","r",stdin);
	int T;
	T=fun.read();
	while(T--)fun.work();
	return 0;
}
/************************************
USER:ANDREW_82
LANG:C++
PROG:baoli
************************************/

你可能感兴趣的:(图论算法,数据结构,搜索,noip,小蒟蒻的noip回头路)