• 蓝桥杯-计蒜客之买书


    必须写一个博客来出出心中这口恶气,因为每次遇到递归的问题都会卡很长时间,这次也不例外(生气的表情:哼)

    题干:

      蒜头君去书店买书,他有 m 元钱,书店里面有 n 本书,每本书的价格为 pi 元。蒜头君很爱学习,想把身上钱都用来买书,并且刚好买 k 本书。请帮蒜头君计算他是否能刚好用 m 元买 k 本书。

    输入格式

      第一行输入 3 个整数 m(1m100000000),n(1n30),k(1kmin(8,n))

      接下来一行输入 n 个整数,表示每本书的价格 pi(1pi100000000)。

    输出格式

      如果蒜头君能刚好用 m 元买 k 本书,输入一行"Yes", 否则输出"No"

    样例输入1

    10 4 4
    1 2 3 4

    样例输出1

    Yes

    样例输入2

    10 4 3
    1 2 3 4

    样例输出2

    No

    问题分析:
      咱们先想一下递归的原理:递归就是重复地做一件事,直到遇到某个条件成立时再停止递归。下面再来看这道题,这道题实质上也在重复地做一件事,即判断是否要买当前的书,如果买了那么接下来应该怎么做;
    如果没买那么接下来又应该怎么做。
      我写的递归函数是这个形式的:void dfs(int mon,int pos,int cnt) ,其中mon代表当前的钱数,pos代表当前正在考虑的是哪一本书(注意:是正在考虑,而不是已经买了或者没买),cnt代表当前已经买了几本书(当然不包括当前正在考虑的这本书)

    注意:写法一是对的,写法二是错误的。原因是(1)式代表的是买书,所以应该减去当前这本书的价格,但是(2)式代表的是不买书,所以他不应该减去这本书的价格 (这一部分看不懂也没关系,与其它部分没有联系)
       还有就是递归的结束条件要把握好,有的题的结束条件很好找,比如求阶乘问题;但有的题的条件不是不好找而是找不全,比如这道题。 所以递归的难点在于找到“重复的过程“和“结束条件”。
    void dfs(int mon,int pos,int cnt)
    {
        if(mon==0 && cnt==k){
            judge=true;
            return ;
        }
        if(mon<=0 || cnt>k){
            return ;
        }
        if(pos>=n){
            return ;
        }
    写法一:
        dfs(mon-price[pos],pos+1,cnt+1); 
        dfs(mon,pos+1,cnt); 
    写法二:
        mon -= price[pos];
        dfs(mon,pos+1,cnt+1); (1)
        dfs(mon,pos+1,cnt);  (2)
    }

    代码如下:

    #include<iostream>
    using namespace std;
    typedef long long LL;
    
    int n,k;
    LL price[35]={0};
    bool judge=false;
    
    void dfs(int mon,int pos,int cnt)
    {
        if(mon==0 && cnt==k){
            judge=true;
            return ;
        }
        if(mon<=0 || cnt>k){
            return ;
        }
        if(pos>=n){
            return ;
        }
        dfs(mon-price[pos],pos+1,cnt+1);
        dfs(mon,pos+1,cnt);
    }
    
    int main()
    {
        LL m;
        while(cin>>m>>n>>k){
            judge=false;
            for(int i=0;i<n;i++){
                cin>>price[i];
            }
            dfs(m,0,0);
            if(judge){
                cout<<"Yes"<<endl;
            }
            else{
                cout<<"No"<<endl;
            }
        }
    }


  • 相关阅读:
    关于回溯与招聘市场
    关于回溯与马
    关于回溯和后宫
    关于兔子
    关于递归和斐波那契数列
    关于递归和汉诺塔
    关于简单汉诺塔
    nodejs报错roll back,because of a error.node.js setup wizard ended prematurel
    fatal error C1859 意外的预编译头错误,只需重新运行编译器
    sqlserver2008 无法设置主体sa的凭据
  • 原文地址:https://www.cnblogs.com/ACPIE-liusiqi/p/8645412.html
Copyright © 2020-2023  润新知