gpt4 book ai didi

c++ - 硬币找零 DP 算法打印所有组合

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:21:31 27 4
gpt4 key购买 nike

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

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

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

但是我改进后的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;
}

最佳答案

看来你复制了太多vector:至少最后的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();
}
}

关于c++ - 硬币找零 DP 算法打印所有组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33353227/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com