zoukankan      html  css  js  c++  java
  • 动态规划:找零钱问题,输出所有可能方案的使用零钱的总张数

    一道面试题,给出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 }
  • 相关阅读:
    垂死挣扎-3
    垂死挣扎-2
    垂死挣扎-1
    【互联网考试系列-1】进程与线程
    【iOS基础学习随笔-2】SQLite的使用
    【iOS面试系列-2】多线程中同步、异步和串行、并行之间的逻辑关系(必考,必须掌握)
    docker
    给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
    621. 任务调度器
    204. 计数质数
  • 原文地址:https://www.cnblogs.com/liugl7/p/11331901.html
Copyright © 2011-2022 走看看