【问题标题】:Coin Change DP Algorithm Print All Combinations硬币找零DP算法打印所有组合
【发布时间】:2016-01-25 23:51:06
【问题描述】:

这里很好地描述了经典的硬币找零问题:http://www.algorithmist.com/index.php/Coin_Change

这里我不仅想知道有多少种组合,还想把它们全部打印出来。我在我的实现中的那个链接中使用了相同的 DP 算法,但是我没有在 DP 表中记录DP[i][j] = count 的组合数量,而是将组合存储在表中。所以我在这个 DP 表中使用了 3D 矢量。

我试图改进我的实现,注意到在查找表时,只需要最后一行的信息,所以我并不需要总是存储整个表。

但是我改进的 DP 解决方案似乎仍然很慢,所以我想知道下面的实现是否存在问题,或者可以进行更多优化。谢谢!

可以直接运行代码:

#include <iostream>
#include <stdlib.h>
#include <iomanip>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

int main(int argc, const char * argv[]) {       

    int total = 10; //total amount
    //available coin values, always include 0 coin value
    vector<int> values = {0, 5, 2, 1}; 
    sort(values.begin(), values.end()); //I want smaller coins used first in the result 

    vector<vector<vector<int>>> empty(total+1); //just for clearing purpose
    vector<vector<vector<int>>> lastRow(total+1);
    vector<vector<vector<int>>> curRow(total+1);


    for(int i=0; i<values.size(); i++) {


        for(int curSum=0; curSum<=total; curSum++){
            if(curSum==0) {
                //there's one combination using no coins               
                curRow[curSum].push_back(vector<int> {}); 

            }else if(i==0) {
                //zero combination because can't use coin with value zero

            }else if(values[i]>curSum){
                //can't use current coin cause it's too big, 
                //so total combination for current sum is the same without using it
                curRow[curSum] = lastRow[curSum];

            }else{
                //not using current coin
                curRow[curSum] = lastRow[curSum];
                vector<vector<int>> useCurCoin = curRow[curSum-values[i]];

                //using current coin
                for(int k=0; k<useCurCoin.size(); k++){

                    useCurCoin[k].push_back(values[i]);
                    curRow[curSum].push_back(useCurCoin[k]);
                }               
            }    
        }        

        lastRow = curRow;
        curRow = empty;
    } 

    cout<<"Total number of combinations: "<<lastRow.back().size()<<endl;
    for (int i=0; i<lastRow.back().size(); i++) {
        for (int j=0; j<lastRow.back()[i].size(); j++) {
            if(j!=0)
                cout<<" ";
            cout<<lastRow.back()[i][j];
        }
        cout<<endl;
    }
    return 0;
}

【问题讨论】:

  • 运行分析器可能会有所帮助。

标签: c++ algorithm vector dynamic-programming coin-change


【解决方案1】:

看来你复制的向量太多了:至少最后一个else可以改写成

// not using current coin
curRow[curSum] = lastRow[curSum];
const vector<vector<int>>& useCurCoin = curRow[curSum - values[i]]; // one less copy here

// using current coin
for(int k = 0; k != useCurCoin.size(); k++){
    curRow[curSum].push_back(useCurCoin[k]);
    curRow[curSum].back().push_back(values[i]); // one less copy here too.
}

即使清理curRow = empty; 是可读的,也可能会创建分配。 最好创建一个函数

void Clean(vector<vector<vector<int>>>& vecs)
{
    for (auto& v : vecs) {
        v.clear();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-05
    • 1970-01-01
    • 2013-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多