POJ 1276 Cash Machine
题目大意:
题解:
多重背包模板题,需要用到二进制拆分,将物品数\(n_i\)拆成\(1,2,4,8,...,2^{k},x(x \leq 2^{k + 1})\),则这些数的组合可以表示\([1,n_i]\)的所有数,就不需要循环从\(1\)跑到\(n_i\)了。
#include <cstring>
#include <iostream>
using namespace std;
#define N 110
int dp[100010], cash, n, cnt, ni, di;
struct Node {
int w, v;
} node[110];
void addNode(int n, int d) {
int p = 1;
while (n) {
if (n >= p) {
node[++cnt].w = d * p;
node[cnt].v = d * p;
n -= p;
p <<= 1;
} else {
node[++cnt].w = d * n;
node[cnt].v = d * n;
n = 0;
}
}
}
int main() {
while (cin >> cash >> n) {
memset(dp, 0, sizeof(dp));
cnt = 0;
for (int i = 1; i <= n; ++i) {
cin >> ni >> di;
addNode(ni, di);
}
for (int i = 1; i <= cnt; ++i) {
for (int j = cash; j >= node[i].w; --j) {
dp[j] = max(dp[j], dp[j - node[i].w] + node[i].v);
}
}
cout << dp[cash] << endl;
}
return 0;
}