zoukankan      html  css  js  c++  java
  • careercup-递归和动态规划 9.8

    9.8 给定数量不限的硬币,币值为25分、10分、5分和1分,编写代码就是n分有几种表示法。

    解法:

    使用回溯法进行解决,实际上就是一个类似枚举的过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

    C++实现代码:

    #include<vector>
    #include<iostream>
    using namespace std;
    
    void helper(vector<int> &denom,int target,vector<int> &path,vector<vector<int> > &res)
    {
        if(target<0)
            return;
        if(target==0)
        {
            res.push_back(path);
            return;
        }
        int i;
        for(i=0;i<(int)denom.size();i++)
        {
            path.push_back(denom[i]);
            helper(denom,target-denom[i],path,res);
            path.pop_back();
        }
    }
    
    vector<vector<int> > makeChange(vector<int> &denom,int target)
    {
        if(denom.empty())
            return vector<vector<int> >();
        vector<vector<int> > res;
        vector<int> path;
        helper(denom,target,path,res);
        return res;
    }
    
    int main()
    {
        vector<int> vec={1,2,3};
        vector<vector<int> > res=makeChange(vec,5);
        for(auto a:res)
        {
            for(auto t:a)
                cout<<t<<" ";
            cout<<endl;
        }
    }

    运行结果:

    其中存在重复的,譬如:1 1 2 1 和 2 1 1 1。虽然顺序不一样,但是表示的同样的划分。

    这是错误的,问题出在哪呢?有序和无序的区别!这个函数计算出来的组合是有序的,也就是它会认为1,2和2,1是不一样的,导致计算出的组合里有大量是重复的。那要怎么避免这个问题呢?1,5和5,1虽然会被视为不一样,但如果它们是排好序的,比如都按从大到小排序,那么就是5,1了,这时就不会重复累计组合数量。可是我们总不能求出答案之后在排序吧,多费劲。这是我们就在递归上动手脚,让它在计算的过程中就按照从大到小的币值来组合。比如,现在我拿了一个25分的硬币,那下一次可以去的币值就是25,10,5,1;如果我拿了一个10分的,下一次可以取的币值就只有10,5,1了;这样一来,就能保证,我只累计了一次,改造后的代码如下:

    #include<vector>
    #include<iostream>
    using namespace std;
    
    void helper(vector<int> &denom,int start,int target,vector<int> &path,vector<vector<int> > &res)
    {
        if(target<0)
            return;
        if(target==0)
        {   
            res.push_back(path);
            return;
        }   
        int i;
        for(i=start;i<(int)denom.size();i++)
        {   
            path.push_back(denom[i]);
         //只能从下标i和i之后的元素开始取 helper(denom,i,target
    -denom[i],path,res); path.pop_back(); } } vector<vector<int> > makeChange(vector<int> &denom,int target) { if(denom.empty()) return vector<vector<int> >(); vector<vector<int> > res; vector<int> path; helper(denom,0,target,path,res); return res; } int main() { vector<int> vec={3,2,1}; vector<vector<int> > res=makeChange(vec,5); for(auto a:res) { for(auto t:a) cout<<t<<" "; cout<<endl; } }

    运行结果:

    [root@localhost 桌面]# ./coin 
    3 2 
    3 1 1 
    2 2 1 
    2 1 1 1 
    1 1 1 1 1 

    #include<iostream>
    using namespace std;
    
    int makeChange(int n,int denom)
    {
        int next_denom=0;
        switch(denom)
        {
        case 25:
            next_denom=10;
            break;
        case 10:
            next_denom=5;
            break;
        case 5:
            next_denom=1;
            break;
        case 1:
            return 1;
        }
        int i;
        int way=0;
        for(i=0;n-i*denom>=0;i++)
        {
            way+=makeChange(n-i*denom,next_denom);
        }
        return way;
    }
    
    int main()
    {
        cout<<makeChange(100,25)<<endl;
    }
  • 相关阅读:
    C# 操作配置文件
    C# Excel操作类
    没有找到 mspdb100.dll 的解决办法
    工厂方法模式
    .Net互操作2
    The certificate used to sign “AppName” has either expired or has been revoked. An updated certificate is required to sign and install the application解决
    手机抓包xcode自带命令行工具配合wireshark实现
    expecting SSH2_MSG_KEX_ECDH_REPLY ssh_dispatch_run_fatal问题解决
    使用ssh-keygen设置ssh无密码登录
    远程复制文件到服务器
  • 原文地址:https://www.cnblogs.com/wuchanming/p/4150731.html
Copyright © 2011-2022 走看看