有n种不同面值的硬币,每种一个;试着用这些硬币凑出整数m
如果有多种方案,输出字典序最小的那个
eg.
input:
3 5
3 2 6
output: 2 3
input:
8 9
5 9 8 7 2 3 4 1
output:
1 3 5
- 说明一:这里的硬币逻辑上是价值和质量相同的物品w[i]=v[i],用m_w_v[]一个数组存放
- 说明二:字典序最小,先将面值由大到小排序,最后按记录结果倒序输出
#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
const int MAXSIZE = 13;
class BAGS
{
public:
BAGS() {
init();
}
~BAGS() {}
void init() {
int n = 0,t=0;
cin >> n >> m_bagCapcity;
for (int i = 0; i < n; i++) {
cin >> t;
m_w_v.push_back(t);
}
sort(m_w_v.begin(), m_w_v.end(), [=](int i, int j)->bool { return i > j; });
for (int i = 0; i < MAXSIZE; i++) {
for (int j = 0; j < MAXSIZE; j++) {
m_choice[i][j] = false;
}
}
}
void getMatchPlan() {
vector<int> maxValue;
for (int i = 0; i < 1+ m_bagCapcity; i++) {
maxValue.push_back(0);
}
getChoiceTable(maxValue);
if (maxValue[m_bagCapcity] != m_bagCapcity) {
printf_s("No soluton.\n");
}
else {
printPlan();
}
}
void getChoiceTable(vector<int>& maxValue) {
for (int i = 0; i < m_w_v.size(); i++) {
for (int cap = m_bagCapcity; cap >= m_w_v[i]; cap--) {
if (maxValue[cap] <= maxValue[cap - m_w_v[i]] + m_w_v[i]) {
maxValue[cap] = maxValue[cap - m_w_v[i]] + m_w_v[i];
m_choice[i][cap] = true;
}
else {
m_choice[i][cap] = false;
}
}
}
}
void printPlan() {
int n = m_w_v.size()-1;
int cap = m_bagCapcity;
while (n >= 0) {
if (m_choice[n][cap]) {
cout<<m_w_v[n]<<" ";
cap -= m_w_v[n];
}
n--;
}
cout << endl;
}
private:
vector<int> m_w_v;
int m_bagCapcity;
bool m_choice[MAXSIZE][MAXSIZE];
};
void testForBag01() {
BAGS test;
test.getMatchPlan();
}
- 要小心下标和表格一致,例如取不取边界值,起点是谁?这里硬币种类从零开始到n-1,而容量[0,capacity]
- 注意更新条件是capacity>当前某个值的权重,而不是大于零