Noip2017 Day2T1 cheese

本文探讨了如何通过深度优先搜索、宽度优先搜索及并查集等算法解决三维空间中奶酪堆叠的问题,旨在判断能否找到合适的奶酪堆叠方案以达到指定高度。文章详细介绍了算法实现细节,并对比了不同算法的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

总结:
编译时重复定义,例如全局变量定义了一遍,多组数组需要清零,又定义了一遍并赋值,但是第二遍没用
Yes写成了yes,No写成了no…爆零
dfs开始点设置vis[]为用过,忘记


#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
long long x[1005],y[1005],z[1005],vis[1005]; 
int T,n,h,r,b[1005][1005],f=0;
double srd=0.0000000000001;
void chk(int i,int j)
{
    long long sij=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]);
    if(2.0*r-sqrt(sij*1.0)+srd>=0.0 || 2.0*r-sqrt(sij)-srd>=0.0)
    {
        b[i][j]=b[j][i]=1;
    }   
}
bool dfs(int t,int sl)//少一个减枝 
{
    if(sl+r>=h) {
        f=1;return 1;
    }
    for(int i=1;i<=n;i++)
    {
        if(b[t][i] && !vis[i] && z[i]>z[t])//下一个球只有比它高才有意义? 
        {
            vis[i]=1;
            dfs(i,z[i]);
            vis[i]=0;
        }
        if(f==1) return 1; 
    }
    return 0;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(x,0,sizeof x);
        memset(y,0,sizeof y);
        memset(z,0,sizeof z); 
        memset(vis,0,sizeof vis);
        memset(b,0,sizeof b);
        f=0;
        scanf("%d%d%d",&n,&h,&r);//先考虑一种情况 
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
        } 
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) if(i!=j) chk(i,j);

//      for(int i=1;i<=n;i++)
//          for(int j=1;j<=n;j++)
//              cout<<i<<","<<j<<","<<b[i][j]<<endl;
        int ys=0;
        for(int i=1;i<=n;i++)
        {
            if(z[i]<=r*1.0)//看哪个奶酪可以作为最下面那一个 
            {
                f=0;
                if(dfs(i,z[i])) 
                {
                    printf("Yes\n");ys=1;
                    break;  
                }
            }
        }
        if(!ys) printf("No\n");
    }

} 

进行了部分优化,否则卡不过去

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
long long h,r; 
int T,n,b[1005][1005],vis[1005],f=0;
//double srd=0.0000001;
struct Node{
    long long x,y,z;
}nod[1005];
inline void chk(int i,int j)
{
    long long sij=(nod[i].x-nod[j].x)*(nod[i].x-nod[j].x)+(nod[i].y-nod[j].y)*(nod[i].y-nod[j].y)+(nod[i].z-nod[j].z)*(nod[i].z-nod[j].z);
    if(2.0*r-sqrt(sij*1.0)>=0.0)
    {
        b[i][j]=b[j][i]=1;
    }   
}
inline int dfs(int t,long long sl)
{
    if(sl+r>=h) {
        f=1;return 1;
    }
    for(register int i=t+1;i<=n;i++)//**************优化部分**********
    {
        if(b[t][i] && !vis[i]) 
        {
            vis[i]=1;
            if(dfs(i,nod[i].z))
                return 1;
        }
    }
    return 0;
}
bool cmp(Node p,Node q)
{
    if(p.z<=q.z) return true;
    else return false;
}
int main()
{
    freopen("cheese.in","r",stdin);
    freopen("cheese.out","w",stdout);
    scanf("%d",&T);
    while(T--)
    {
        memset(vis,0,sizeof vis);
        memset(b,0,sizeof b);
        f=0;
        scanf("%d%lld%lld",&n,&h,&r);//先考虑一种情况 
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld",&nod[i].x,&nod[i].y,&nod[i].z);
        } 
        **sort(nod+1,nod+n+1,cmp);//**************优化部分**********
        for(int i=1;i<=n;i++)
            for(int j=1;j<i;j++)
                chk(i,j);**
//      for(int i=1;i<=n;i++)
//          for(int j=1;j<=n;j++)
//              cout<<i<<","<<j<<","<<b[i][j]<<endl;
        int ys=0;
        for(int i=1;i<=n;i++)
        {
            if(nod[i].z<=r*1.0)//看哪个奶酪可以作为最下面那一个 
            {
                f=0;vis[i]=1;
                if(dfs(i,nod[i].z)) 
                {
                    printf("Yes\n");ys=1;
                    break;  
                }
            }
            if(ys==1) break;
        }
        if(!ys) printf("No\n");
    }
} 
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
long long h,r; 
int T,n,b[1005][1005],vis[1005],f=0;
//double srd=0.0000001;
struct Node{
    long long x,y,z;
}nod[1005];
inline void chk(int i,int j)
{
    long long sij=(nod[i].x-nod[j].x)*(nod[i].x-nod[j].x)+(nod[i].y-nod[j].y)*(nod[i].y-nod[j].y)+(nod[i].z-nod[j].z)*(nod[i].z-nod[j].z);
    if(2.0*r-sqrt(sij*1.0)>=0.0)
    {
        b[i][j]=b[j][i]=1;
    }   
}
inline int dfs(int t,long long sl)
{
    if(sl+r>=h) {
        f=1;return 1;
    }
    for(register int i=1;i<=n;i++)
    {
        if(b[t][i] && !vis[i])
        {
            vis[i]=1;
            if(dfs(i,nod[i].z))
                return 1;
        }
    }
    return 0;
}
int main()
{
    freopen("cheese.in","r",stdin);
    freopen("cheese.out","w",stdout);
    scanf("%d",&T);
    while(T--)
    {
        memset(vis,0,sizeof vis);
        memset(b,0,sizeof b);
        f=0;
        scanf("%d%lld%lld",&n,&h,&r);//先考虑一种情况 
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld",&nod[i].x,&nod[i].y,&nod[i].z);
            for(int j=1;j<i;j++)//*******优化不封*******
                chk(i,j);
        } 
//        sort(nod+1,nod+n+1,cmp);//
//      for(int i=1;i<=n;i++)
//          for(int j=1;j<=n;j++)
//              cout<<i<<","<<j<<","<<b[i][j]<<endl;
        int ys=0;
        for(int i=1;i<=n;i++)
        {
            if(nod[i].z<=r*1.0)//看哪个奶酪可以作为最下面那一个 
            {
                f=0;vis[i]=1;
                if(dfs(i,nod[i].z)) 
                {
                    printf("Yes\n");ys=1;
                    break;  
                }
            }
            if(ys==1) break;
        }
        if(!ys) printf("No\n");
    }
} 

宽搜
平时惯用的变量,因为题目要求,导致更改,从而习惯性保持变量规则,出现错误

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int t,n,T;
long long h,r;
struct NODE{
    long long x,y,z;
}nod[1005];
int dis[1005][1005],vis[1005],ui[1000005];
void dist(int p,int q)
{
    long long lpq=(nod[p].x-nod[q].x)*(nod[p].x-nod[q].x)+(nod[p].y-nod[q].y)*(nod[p].y-nod[q].y)+(nod[p].z-nod[q].z)*(nod[p].z-nod[q].z);
    if(sqrt(lpq*1.0)-2.0*r<=0.0)
        dis[p][q]=dis[q][p]=1;
}
bool bfs(int u)
{
    int hd=1,tl=1;
    ui[hd]=u;
    if(nod[u].z+r>=h) return true;//这里少打一个等于号 
    while(hd<=tl)
    {
//      int tmp=0;
        for(int i=1;i<=n;i++)
        {
            if(dis[ui[hd]][i] && !vis[i])//这里再一次写错成dis[u][i] 
            {                            //dis[ui[h]][i]
                if(nod[i].z+r>=h)
                    return true;
                else
                {
                    vis[i]=1;
//                  tmp=1;
                    ui[++tl]=i; 
                }       
            }   
        }   
//      if(tmp==0) return false;
        hd++;
    }
//  if(tmp==0) 
    return false;
}

int main()
{
    freopen("cheese.in","r",stdin);
    freopen("cheese.out","w",stdout);
    scanf("%d",&T);
    for(int k=1;k<=T;k++)
    {
        memset(vis,0,sizeof vis);
        memset(dis,0,sizeof dis);
        memset(ui,0,sizeof ui);
        scanf("%d%lld%lld",&n,&h,&r);
        long long mxz=0.0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld",&nod[i].x,&nod[i].y,&nod[i].z);
            for(int j=1;j<i;j++)
                dist(i,j);
        }

//      for(int i=1;i<=n;i++)
//          for(int j=1;j<=n;j++)
//              cout<<i<<","<<j<<","<<dis[i][j]<<endl;
        int ys=0;
        for(int i=1;i<=n;i++)
        {
            if(nod[i].z<=r)
            {
                vis[i]=1;
                if(bfs(i)){
                    cout<<"Yes"<<endl;
                    ys=1;
                    break;  
                } 
            }
        }
        if(ys==0) cout<<"No"<<endl;
    }
}

并查集

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;

const int MAXN = 1010;

int n, h, r;
long long r2;
int x[MAXN], y[MAXN], z[MAXN];
int Test;
int fa[MAXN];
inline int findf(int nd)
{ return fa[nd]?fa[nd]=findf(fa[nd]):nd; }
inline void link(int i, int j)
{
    i = findf(i), j = findf(j);
    if (i != j)
        fa[i] = j;
}

inline bool touch(int i, int j)
{
    return (long long)(x[i]-x[j])*(x[i]-x[j])+(long long)(y[i]-y[j])*(y[i]-y[j]) <= r2-(long long)(z[i]-z[j])*(z[i]-z[j]);
}

const int S = MAXN-1, T = MAXN-2;

int main()
{
    freopen("cheese.in", "r", stdin);
    freopen("cheese.out", "w", stdout);
    scanf("%d", &Test);
    while (Test--) {
        memset(fa, 0, sizeof fa);
        scanf("%d%d%d", &n, &h, &r), r2 = (long long)r*r*4ll;
        for (register int i = 1; i <= n; i++) scanf("%d%d%d", &x[i], &y[i], &z[i]);
        for (register int i = 1; i <= n; i++) {
            if (abs(z[i]) <= r) link(S, i);
            if (abs(h-z[i]) <= r) link(i, T);
            for (register int j = i+1; j <= n; j++) {
                if (touch(i, j))
                    link(i, j);
            }
            if (findf(S) == findf(T)) break;
        }
        if (findf(S) == findf(T)) puts("Yes");
        else puts("No");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值