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