【比赛】NOIP2017 奶酪

 

 

开始看到题以为是计算几何,后面发现不是,然后秒掉了。

可能写SPFA写多了,别人都是并查集做的,我用的是SPFA。

不过无所谓,我们把题目中的下底面和上表面看成两个点,那么就是求这两个点的连通性,如果连通,出Yes,否则出No。

转换成图论,如果两个洞的半径乘2大于等于两洞球心之间的距离,那么这两个洞就直接相通,连边,总共平方复杂度建图。

然后跑SPFA,如果终点的dis不为inf,就可到达。

 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int MAXN=1000+10,inf=0x3f3f3f3f;
int T,n,h,p[MAXN],d[MAXN],to[MAXN*MAXN*2],nex[MAXN*MAXN*2],beg[MAXN],w[MAXN*MAXN*2],e,s,t;
ll r;
struct node{
    int x,y,z;
};
node hole[MAXN];
inline void read(int &x)
{
    int data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=(data<<3)+(data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
inline bool connect(int i,int j)
{
    if(4ll*r*r-(ll)(hole[i].x-hole[j].x)*(ll)(hole[i].x-hole[j].x)>=(ll)(hole[i].y-hole[j].y)*(ll)(hole[i].y-hole[j].y)+(ll)(hole[i].z-hole[j].z)*(ll)(hole[i].z-hole[j].z))return true;
    else return false;
}
inline void insert(int x,int y,int z)
{
    to[++e]=y;
    nex[e]=beg[x];
    beg[x]=e;
    w[e]=z;
}
inline void Build()
{
    for(register int i=1;i<=n;++i)
        for(register int j=i+1;j<=n;++j)
            if(connect(i,j))insert(i,j,1),insert(j,i,1);
    for(register int i=1;i<=n;++i)
        if(hole[i].z-r<=0)insert(s,i,1);
    for(register int i=1;i<=n;++i)
        if(hole[i].z+r>=h)insert(i,t,1);
}
inline void SPFA()
{
    for(register int i=1;i<=t;++i)d[i]=inf;
    queue<int> q;
    q.push(s);
    p[s]=1;
    d[s]=0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        p[x]=0;
        for(register int i=beg[x];i;i=nex[i])
            if(d[to[i]]>d[x]+w[i])
            {
                d[to[i]]=d[x]+w[i];
                if(!p[to[i]])
                {
                    p[to[i]]=1;
                    q.push(to[i]);
                }
            }
    }
}
inline void init()
{
    e=0;
    memset(beg,0,sizeof(beg));
    memset(p,0,sizeof(p));
}
int main()
{
    freopen("cheese.in","r",stdin);
    freopen("cheese.out","w",stdout);
    read(T);
    while(T--)
    {
        init();
        read(n);read(h);scanf("%lld",&r);
        s=n+1,t=n+2;
        for(register int i=1;i<=n;++i)read(hole[i].x),read(hole[i].y),read(hole[i].z);
        Build();
        SPFA();
        if(d[t]<inf)printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
NOIP2017 奶酪

 

posted @ 2017-12-07 20:23  HYJ_cnyali  阅读(722)  评论(0编辑  收藏  举报