动态规划:找零钱问题,输出所有可能方案的使用零钱的总张数

一道面试题,给出1、5、10、20、50、100纸币的张数,再给一个钱数,问能否组成? 能组成的话,输出各个方案用的纸币的张数的和;不能则输出-1。

这道题的很明显是背包问题,涉及到背包问题求方案数、输出具体方案。

动态规划求解背包问题输出方案的话,在于不要使用一维dp,这样动态规划的转移过程就被抹去了,而是用二维dp的话,就可以将求得最优解的状态转移过程保留下来。

这道题的解法即是如此。先通过普通的背包问题求方案数,得到有可能的方案的总数。再通过得到最优解的动态规划的二维转移矩阵得到所有可能的方案。

 

 1 #include <iostream>
 2 #include <sstream>
 3 #include <vector>
 4 #include <iomanip>
 5 //#include <bits/stdc++.h>
 6 using namespace std;
 7 
 8 //给出1、5、10、20、50、100纸币的张数,再给一个钱数,问能否组成?
 9 //能组成的话,输出各个方案用的纸币的张数的和;不能则输出-1 
10 
11 int process(std::string strTargetNum, std::string strValueSequences) {
12     int targetNum = std::atoi(strTargetNum.c_str());
13     //int targetNum = std::stoi(strTargetNum);
14     istringstream temp(strValueSequences);
15     vector<int> num;
16     int cur;
17     while (temp >> cur) {
18         num.push_back(cur);
19     }
20 
21     vector<int> charge = { 1, 5, 10, 20, 50, 100 };  
22 
23     int N = charge.size(), V = targetNum;
24     int dp[101][1000];
25     memset(dp, 0, sizeof(dp));
26     for (int i = 0; i <= V; i++) {
27         if (i%charge[0] == 0 && i/charge[0]<=num[0] )
28             dp[0][i] = 1;
29     }
30 
31     for (int i = 0; i < N; i++) {
32         dp[i][0] = 1;
33     }
34     
35     //dp[i][j]代表使用前i种零钱组成钱数j的方案数   
36     for (int i = 1; i<N; i++) {
37         for (int j = 1; j <= V; j++) {
38             int count_temp = 0;
39             for (int k = 0; k <= num[i] && k*charge[i] <= j; k++) {
40                 count_temp += dp[i-1][j - k*charge[i] ];
41             }
42             dp[i][j] = count_temp;
43         }
44     }
45 
46     /*
47     for (int i = 0; i < N; i++) {
48         for (int j = 0; j <= V; j++) {
49             cout<<setw(2) << dp[i][j] << " ";
50         }
51         cout << endl;
52     }
53     */
54 
55     /*
56     int count = 0;
57     int vol = V;
58     for (int i = N - 1; i >= 1; i--) {
59         //for (int j = 1; j < V; j++) {
60             for (int k = 0; k <= num[i]; k++) {
61                 if (dp[i-1][j-k*charge[i]]!=0   ) {
62 
63                 }
64 
65             }
66         //}
67     } 
68     */
69 
70     return dp[N-1][V];     
71 }
72 
73 int main(int argc, const char * argv[]) {
74 
75     std::string strValueSequences;
76     //std::cin >> strValueSequences;
77     std::getline(std::cin, strValueSequences);
78 
79     std::string strChargeNum;
80     std::cin >> strChargeNum;
81     //    targetNum = std::stoi(strChargeNum);
82 
83     //process
84     int lenSum = process(strChargeNum, strValueSequences);
85 
86     std::cout << lenSum << std::endl;
87 
88     system("pause");
89     return 0;
90 }

 

posted on 2019-08-10 16:04  逸阳  阅读(1114)  评论(0编辑  收藏  举报

导航