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

解法:

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

C++实现代码:

  1. #include<vector>
  2. #include<iostream>
  3. using namespace std;
  4.  
  5. void helper(vector<int> &denom,int target,vector<int> &path,vector<vector<int> > &res)
  6. {
  7. if(target<)
  8. return;
  9. if(target==)
  10. {
  11. res.push_back(path);
  12. return;
  13. }
  14. int i;
  15. for(i=;i<(int)denom.size();i++)
  16. {
  17. path.push_back(denom[i]);
  18. helper(denom,target-denom[i],path,res);
  19. path.pop_back();
  20. }
  21. }
  22.  
  23. vector<vector<int> > makeChange(vector<int> &denom,int target)
  24. {
  25. if(denom.empty())
  26. return vector<vector<int> >();
  27. vector<vector<int> > res;
  28. vector<int> path;
  29. helper(denom,target,path,res);
  30. return res;
  31. }
  32.  
  33. int main()
  34. {
  35. vector<int> vec={,,};
  36. vector<vector<int> > res=makeChange(vec,);
  37. for(auto a:res)
  38. {
  39. for(auto t:a)
  40. cout<<t<<" ";
  41. cout<<endl;
  42. }
  43. }

运行结果:

其中存在重复的,譬如: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了;这样一来,就能保证,我只累计了一次,改造后的代码如下:

  1. #include<vector>
  2. #include<iostream>
  3. using namespace std;
  4.  
  5. void helper(vector<int> &denom,int start,int target,vector<int> &path,vector<vector<int> > &res)
  6. {
  7. if(target<)
  8. return;
  9. if(target==)
  10. {
  11. res.push_back(path);
  12. return;
  13. }
  14. int i;
  15. for(i=start;i<(int)denom.size();i++)
  16. {
  17. path.push_back(denom[i]);
         //只能从下标i和i之后的元素开始取
  18. helper(denom,i,target-denom[i],path,res);
  19. path.pop_back();
  20. }
  21. }
  22.  
  23. vector<vector<int> > makeChange(vector<int> &denom,int target)
  24. {
  25. if(denom.empty())
  26. return vector<vector<int> >();
  27. vector<vector<int> > res;
  28. vector<int> path;
  29. helper(denom,,target,path,res);
  30. return res;
  31. }
  32.  
  33. int main()
  34. {
  35. vector<int> vec={,,};
  36. vector<vector<int> > res=makeChange(vec,);
  37. for(auto a:res)
  38. {
  39. for(auto t:a)
  40. cout<<t<<" ";
  41. cout<<endl;
  42. }
  43. }

运行结果:

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

  1. #include<iostream>
  2. using namespace std;
  3.  
  4. int makeChange(int n,int denom)
  5. {
  6. int next_denom=;
  7. switch(denom)
  8. {
  9. case :
  10. next_denom=;
  11. break;
  12. case :
  13. next_denom=;
  14. break;
  15. case :
  16. next_denom=;
  17. break;
  18. case :
  19. return ;
  20. }
  21. int i;
  22. int way=;
  23. for(i=;n-i*denom>=;i++)
  24. {
  25. way+=makeChange(n-i*denom,next_denom);
  26. }
  27. return way;
  28. }
  29.  
  30. int main()
  31. {
  32. cout<<makeChange(,)<<endl;
  33. }

careercup-递归和动态规划 9.8的更多相关文章

  1. 70. Climbing Stairs【leetcode】递归,动态规划,java,算法

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...

  2. 算法 递归 迭代 动态规划 斐波那契数列 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. C#递归、动态规划计算斐波那契数列

    //递归         public static long recurFib(int num)         {             if (num < 2)              ...

  4. 面试题目——《CC150》递归与动态规划

    面试题9.1:有个小孩正在上楼梯,楼梯有n个台阶,小孩一次可以上1阶.2阶或者3阶.实现一个方法,计算小孩有多少种上楼梯的方式. 思路:第4个数是前三个数之和 注意:能不能使用递归,能不能建立一个很大 ...

  5. python---通过递归和动态规划策略解决找零钱问题

    也是常见套路. # coding = utf-8 def rec_mc(coin_value_list, change, know_results): min_coins = change if ch ...

  6. Idea 02.暴力递归与动态规划(1)

    1,关键词解释 1.1 暴力递归: 1, 把问题转化为规模缩小了的同类问题的子问题 2, 有明确的不需要继续进行递归的条件(base case) 3, 有当得到了子问题的结果之后的决策过程 4, 不记 ...

  7. scramble-string——两个字符串经过树化并旋转后是否一致、递归、动态规划

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

  8. OptimalSolution(1)--递归和动态规划(1)斐波那契系列问题的递归和动态规划

    一.斐波那契数列 斐波那契数列就是:当n=0时,F(n)=0:当n=1时,F(n)=1:当n>1时,F(n) = F(n-1)+F(n-2). 根据斐波那契数列的定义,斐波那契数列为(从n=1开 ...

  9. 递归,动态规划,找最短路径,Help Jimmy

    题目链接:http://poj.org/problem?id=1661 解题报告: 1.老鼠每次来到一块木板上都只有两条路可以走,可以使用递归 #include <stdio.h> #in ...

  10. 《Cracking the Coding Interview》——第9章:递归和动态规划——题目10

    2014-03-20 04:15 题目:你有n个盒子,用这n个盒子堆成一个塔,要求下面的盒子必须在长宽高上都严格大于上面的.如果你不能旋转盒子变换长宽高,这座塔最高能堆多高? 解法:首先将n个盒子按照 ...

随机推荐

  1. 如何用CURL并解释JSON

    CURL *curl; CURLcode res; struct curl_slist *headers=NULL; // init to NULL is important headers = cu ...

  2. 总结一下SQL语句中引号(')、quotedstr()、('')、format()在SQL语句中的用法

    总结一下SQL语句中引号(').quotedstr().('').format()在SQL语句中的用法 日期:2005年6月1日 作者:seasky212 总结一下SQL语句中引号(').quoted ...

  3. Android ImageButton | Button | TextView 点击和触摸效果

    ImageButton------------------------------------------------> 一.Java  代码: 在drawable目录下添加新的xml文件 bu ...

  4. dojo自定义Widget

    使dojo AMD规范进行widget 定义,开始的时候一直找不到自己定义的widget模块的位置,经过探索,总算有收获,我这个人有毛病,脑子里不允许有一些想不通的问题,一旦有了问题,就非常难受,心里 ...

  5. 【HDOJ】1462 Word Crosses

    字符串水题,这么做可能比较巧妙. /* 1462 */ #include <iostream> #include <string> #include <map> # ...

  6. hdu4597Play Game(记忆化)

    链接 通化邀请赛的题 貌似不怎么难 记忆化DP 状态方程类似于2维的 只是变成了4维  每次有四种方向去搜 取最棒的 判断好边界条件 #include <iostream> #includ ...

  7. [HDU 5029] Relief grain

    Relief grain Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others)T ...

  8. 对SharePoint 2007数据库中一些数据表的使用

    转:http://blog.csdn.net/ma_jiang/article/details/6553392 在工作中接触了一些SharePoint的数据库中的一些表.在此做个总结. 一位高手告诉我 ...

  9. tomcat7 使用log4j进行日志记录

    将 tomcat-juli.jar 文件放置到 $CATALINA_BASE/bin 目录(实际上,该目录下已经有了) 从 log4j 网站下载 jar 包,并放置于 $CATALINA_BASE/l ...

  10. Tdxtreelist 行变色

    ACanvas.Font.Color := clRed;   //如果有加印的  变颜色