BNUOJ 29376 沙漠之旅 // 第十一届北京师范大学程序设计竞赛决赛

本文介绍了一道经典的算法题目——沙漠之旅,任务是判断是否可以通过携带特定数量的油桶完成一次穿越沙漠的旅程。文章提供了两种解题思路及代码实现,分别是通过标记组合距离的方法和递归搜索方法。

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

沙漠之旅

Time Limit: 1000ms
Memory Limit: 65536KB
64-bit integer IO format:  %lld      Java class name:  Main
Type: 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •                   
  • “小胖要穿越一片沙漠,小胖开着一辆大吉普,小胖的吉普油耗高,吉普能放四桶油。”

    这就是人人会唱的沙漠之歌~~体现了小胖拔群的聪明才智。

    小胖的问题是这样的:现在需要驾车穿越一片沙漠,总的行驶路程为L。小胖的吉普装满油能行驶X距离,同时其后备箱最多能放下四桶油。在起点有N种汽油,每种汽油都有无限桶,一桶能行驶距离Ai。现在小胖想知道:能不能恰好带四桶油,再加上出发前装满的油,使得恰好能行驶L距离。

    Input

    第一行一个正整数T(1 <= T <= 50),表示数据的组数。

    接下来T组数据,每组数据的第一行是三个整数L(1 <= L <= 1000),X(1 <= X <= L),N(1 <= N <= 1000)。

    接下来N行,每行一个正整数Ai(1 <= Ai <= 1000),表示第i种汽油一桶能行驶的距离。

    Output

    对于每组数据输出一行,若能输出“Yes”,否则输出“No”

    Sample Input

    1
    20 9 2
    2
    3
    

    Sample Output

    Yes

    Source

    Author

    zhaoli

    题意很简单就不说啦。
    思路:
            1.用数组标记把任意两个Ai的和标记一下,之后看这些和中有没有相加等于L-X的,这个思路容易理解;
            2.用搜索写;


    代码:
             
       
         
    #include<stdio.h>
    #include<string.h>
    int a[1005];
    int vis[2005];
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n,l,x,m;
            scanf("%d %d %d",&l,&x,&n);
            m=l-x;
            memset(vis,0,sizeof(vis));
            for(int i=1; i<=n; i++)
            {
                scanf("%d",&a[i]);
            }
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                {
                    vis[a[i]+a[j]]=1;
                }
            }
            int flag=0;
    //不知道为什么这样写明明一样却一直RE
    //        for(int i=1;i<=n;i++)
    //        {
    //            for(int j=1;j<=n;j++)
    //            {
    //                if(vis[m-a[i]-a[j]]==1)//m-a[j]-a[i]可能是负数所以不能这么写
    //                {
    //                    printf("Yes\n");
    //                    flag=1;
    //                    break;
    //                }
    //            }
    //            if(flag==1)
    //            {
    //                break;
    //            }
    //        }
            for(int i=0; i<=m; i++)
            {
                if(vis[i]==1&&vis[m-i]==1)
                {
                    printf("Yes\n");
                    flag=1;
                    break;
                }
            }
            if(flag==0)
            {
                printf("No\n");
            }
        }
    }
    



    搜索
        
    #include<stdio.h>
    #include<string.h>
    int a[1005];
    int n,m,flag;
    void bfs(int sum,int s,int t)
    {
        int next;
        if(s>4||sum>m||flag==1)
        {
            return ;
        }
        if(s==4&&sum==m)
        {
            flag=1;
            return ;
        }
        for(int i=t;i<n;i++)
        {
            next=sum+a[i];
            bfs(next,s+1,i);
        }
        return ;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int l,x;
            scanf("%d%d%d",&l,&x,&n);
            m=l-x;
            for(int i=0;i<n;i++)
            {
                scanf("%d",&a[i]);
            }
            flag=0;
            for(int i=0;i<n;i++)
            {
                if(flag==1)
                {
                    break;
                }
                bfs(0,0,i);
            }
            if(flag)
                printf("Yes\n");
            else
                printf("No\n");
        }
    }
    

             
    评论 2
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值