动态规划是一种算法思想,可以简单解释为将复杂问题分解为许多个子问题,在无后效性的前提下一一解决,最后得到原复杂问题的最优解。
1.最少硬币问题
有n种硬币,面值为v1,v2,....vn,数量无限。输入非负整数s,选用硬币,使其和为s。输出最少硬币的组合的数量。
易得其状态转移方程为ans[i]=min(ans[i],ans[i-v[j]]+1) (j=1,2...n)其中ans[i]表示硬币之和,v[j]表示硬币种类,此题本质为背包问题。
2.打印最少硬币的组合
把dp的代码改为:
if(ans[i]>ans[i-v[i]]+1){//用的硬币变了 ans_path[i]=v[i]; //在每个金额上记录路径,即某个硬币的面值 ans[i]=ans[i-v[i]]+1; //递推式 }
3.所有硬币组合
有n种硬币,面值为v1,v2,....vn,数量无限。输入非负整数s,选用硬币,使其和为s。输出所有可能的硬币组合的数量。
其状态转移方程为dp[i]+=dp[i-v[j]] (j=1,2,3,...n)
例题
Coin Change
Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 34000    Accepted Submission(s): 12212
Problem Description
Suppose there are 5 types of coins: 50-cent, 25-cent, 10-cent, 5-cent, and 1-cent. We want to make changes with these coins for a given amount of money.
For example, if we have 11 cents, then we can make changes with one 10-cent coin and one 1-cent coin, or two 5-cent coins and one 1-cent coin, or one 5-cent coin and six 1-cent coins, or eleven 1-cent coins. So there are four ways of making changes for 11 cents with the above coins. Note that we count that there is one way of making change for zero cent.
Write a program to find the total number of different ways of making changes for any amount of money in cents. Your program should be able to handle up to 100 coins.
For example, if we have 11 cents, then we can make changes with one 10-cent coin and one 1-cent coin, or two 5-cent coins and one 1-cent coin, or one 5-cent coin and six 1-cent coins, or eleven 1-cent coins. So there are four ways of making changes for 11 cents with the above coins. Note that we count that there is one way of making change for zero cent.
Write a program to find the total number of different ways of making changes for any amount of money in cents. Your program should be able to handle up to 100 coins.
Input
The input file contains any number of lines, each one consisting of a number ( ≤250 ) for the amount of money in cents.
Output
For each input line, output a line containing the number of different ways of making changes with the above 5 types of coins.
Sample Input
11
26
Sample Output
4
13
  此题与3的区别在于硬币的数量有限,这就需要建立第二个维度来存储硬币的数量这个状态了。
我们设dp[i][j]为使用了j个硬币,和为i的方案数量。
  其状态转移方程为:dp[i][j]+=dp[i-v[k]][j-1]。即使用了j个硬币,和为i的方案数量为原数量加上使用了j-1个硬币何为i-v[k]的方案数,其中v[k]表示第k种硬币的金额。
  代码如下所示
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int v[5]={1,5,10,25,50}; int dp[255][105]; int main(){ memset(dp,0,sizeof(dp)); dp[0][0]=1; int n; for(int k=0;k<=4;k++){ for(int j=1;j<=100;j++){ for(int i=v[k];i<=250;i++){ dp[i][j]+=dp[i-v[k]][j-1]; } } } int ans[255]={0}; for(int i=0;i<=250;i++){ for(int j=0;j<=100;j++){ ans[i]+=dp[i][j]; } } while(~scanf("%d",&n)){ printf("%d\n",ans[n]); } return 0; }
 
                    
                     
                    
                 
                    
                 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号