Exercise(3):最少硬币问题
2016-04-22 20:15
375 查看
/* 陈潼升 最少硬币问题 问题描述 设有n 种不同面值的硬币,各硬币的面值存于数组T[1:n]中。现要用这些面值的硬币来找钱。 可以使用的各种面值的硬币个数存于数组Coins[1:n]中。对任意钱数0≤m≤20001,设计一个用最少硬币找钱m的方法。 编程任务:对于给定的1≤n≤10,硬币面值数组T和可以使用的各种面值的硬币个数数组Coins,以及钱数m,0≤m≤20001,编程计算找钱m的最少硬币数。 Input 输入包括多组测试数据,每组输入的第一行中只有1 个整数给出n的值,第2 行起每行2 个数,分别是T[j]和Coins[j]。每组输入最后1 行是要找的钱数m。 Output 对于每组输入数据,输出一行,即计算出最少硬币数。问题无解时输出-1。 Sample Input 3 1 3 2 3 5 3 18 Sample Output 5 */ /* 将一个问题分裂成n个子问题,求出子问题的解并用子问题的解出问题的答案。即为动规 问题分析 : 给m找零 可分为 找1块,找2块,找3块,找4块......找m块。 定义长度为m的数组dp[1...m],用其存放一系列子问题的结果, 即dp[i]为要凑i块钱所需最少硬币数,则dp[m]为本题答案. 当前要找的钱数为i(1<i<m); 当前所试探的硬币面值为k; 1、当i和k相等时,结果为1,即dp[i] = 1; 2、当i大于k时,若dp[i]为0(即未赋过值),且dp[i-k]不为0(即从i元中刨去k元后剩下的钱可以找开) 则dp[i] = dp[i-k]+1; 若dp[i]不为0(即已赋值), 则dp[i] = min( dp[i-k]+1, dp[i] ) 即dp[i]为dp[i-k]和dp[i]中的较小者。 3、由以上2点得dp[i]的动态转移方程为: dp[i] = min( dp[k], dp[k-t[i]]+1 ) t[i]<=k<=m */ #include <iostream> #define MAX 20001 #define MAXLEN 99999999999 using namespace std; int min(int,int); int main() { int n; // 输入 硬币种数并检测 cin>>n; if(n<1 || n>10) return 0; int *t = new int[n+1]; // t[n+1]存放各种硬币的面值 int *coins = new int[n+1]; // coins[n+1]存放各种硬币的个数 int i,j,k; // i,j,k为循环变量 for(i=1;i<n+1;i++) // 输入 各种硬币面值t[i] 各种硬币个数coins[i] { cin>>t[i]>>coins[i]; } int m, dp[20002]; // dp[20002]存放一系列子找零问题的结果 cin>>m; for(i=1;i<m+1;i++) // 因为要取最小,因此要初始化为(大大地 :drastically)数 dp[i] = MAXLEN; dp[0] = 0; for(i=1;i<=n;i++) // 各种硬币 for(j=1;j<=coins[i];j++) // 各种硬币的个数 for(k=m;k>=t[i];k--) { // 动态转移方程 dp[k] = min(dp[k-t[i]]+1,dp[k]); } cout<<dp[m]<<endl; // dp[m]即为所求结果 return 0; } int min(int a,int b) { return (a<b?a:b); }
相关文章推荐
- 利用mycat实现基于mysql5.5主从复制的读写分离
- 立方尾不变
- leetcode——330——Patching Array
- 稀疏自编码器一览表
- java程序中java对象存储和内存分配的原理?
- 杭州4--22
- 搭建Hadoop2集群出现Datanode启动不了的问题及解决办法
- 利用mycat实现基于mysql5.5主从复制的读写分离
- 0422-团队项目开发
- 第一冲刺阶段工作总结04
- 【LeetCode】LeetCode——第12题:Integer to Roman
- Jsonp手机号查询Jquery格式
- Exercise(2):最大连续子序列和
- 蚂蚁爬竹竿问题
- 第九周项目2:深复制体验(2)
- AFN小结(简单的封装)
- 不翻墙,利用国内源下载Android 源码
- PLSQL_PROFILER
- HDU 1863 畅通工程(Kruskal)
- LeetCode 71. Simplify Path