题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2844
算是一个小变式
这道题考对背包问题的理解
cost和weight在此题是一致的
这保证对一个地方不会出现重复更新
然后跑一遍多重背包之后
【dp[]中“dp[i] == i”的位置就说明在此处有一个“更新” 即可以让总额恰好为i】
#include <cstdio> #include <cstdlib> #include <ctime> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> #include <stack> #include <set> #include <queue> #include <vector> using namespace std; typedef long long ll; const int maxn = 110; const int maxm = 100010; const int INF = 100000; int a[maxn], c[maxn]; int dp[maxm]; int V; void ZeroOnePack(int cost, int weight) { for(int i = V; i >= cost; i--) { dp[i] = max(dp[i], dp[i-cost] + weight); } } void CompletePack(int cost, int weight) { for(int i = cost; i <= V; i++) { dp[i] = max(dp[i], dp[i-cost] + weight); } } void MultiplePack(int cost, int weight, int amount) { if(cost*amount >= V) { CompletePack(cost, weight); return; } int k = 1; while(k < amount) { ZeroOnePack(k*cost, k*weight); amount = amount - k; k *= 2; } ZeroOnePack(amount*cost, amount*weight); } int main() { //freopen("in.txt", "r", stdin); int n, m; while(scanf("%d%d", &n, &m) == 2 && n != 0 && m != 0) { memset(dp, 0, sizeof(dp)); for(int i = 0; i < n; i++) scanf("%d", &a[i]); for(int i = 0; i < n; i++) scanf("%d", &c[i]); V = m; for(int i = 0; i < n; i++) { MultiplePack(a[i], a[i], c[i]); } int ans = 0; for(int i = 1; i <= m; i++) { if(dp[i] == i) ans++; } printf("%d ", ans); } return 0; }