动态规划:找零钱问题,输出所有可能方案的使用零钱的总张数
一道面试题,给出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 }