動態規划:找零錢問題,輸出所有可能方案的使用零錢的總張數


一道面試題,給出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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM