noip2017 Day2 T1——cheese

38 篇文章 0 订阅
20 篇文章 0 订阅

说一道题水,要么是它真的水,要么是你还没有用代码实现过它----Jerry

题目:

分析:

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

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

代码实现

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

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

code:(dfs爆搜)

#include<bits/stdc++.h>
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<bits/stdc++.h>
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
************************************/
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AndrewMe8211

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值