多重背包

来源:互联网 发布:随机过程教材 知乎 编辑:程序博客网 时间:2024/06/04 23:29

poj 1742

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAXN = 100010;int n, m;bool dp[MAXN];int a[MAXN], c[MAXN];int queue[MAXN];int main() {while(~scanf("%d%d", &n, &m)) {if(!n && !m) break;memset(dp, 0, sizeof(dp));dp[0] = true;for(int i = 1; i <= n; i++) scanf("%d", &a[i]);for(int i = 1; i <= n; i++) scanf("%d", &c[i]);//二进制优化/****************for(int i = 1; i <= n; i++) {if(c[i] * a[i] >= m) {for(int j = a[i]; j <= m; j++)if(dp[j - a[i]]) dp[j] = true;}else {int k = 1;while(k <= c[i]) {for(int j = m; j >= k * a[i]; j--)if(dp[j - k * a[i]]) dp[j] = true;c[i] -= k;k <<= 1;}for(int j = m; j >= c[i] * a[i]; j--)if(dp[j - c[i] * a[i]]) dp[j] = true;}}***************///单调队列优化//由于每种状态只有0 1两种值,所以这里的队列并非单调队列,借用sum保存队列里的和,很巧妙Orz...for(int i = 1; i <= n; i++) {if(c[i] * a[i] >= m) {for(int j = a[i]; j <= m; j++)if(dp[j - a[i]]) dp[j] = true;}else {for(int d = 0; d < a[i]; d++) {int sum = 0, st = 0, ed = -1;for(int v = d; v <= m; v += a[i]) {if(ed - st == c[i]) {sum -= queue[st++];}queue[++ed] = dp[v];sum += dp[v];if(!dp[v] && sum) dp[v] = true;}}}}int ans = 0;for(int i = 1; i <= m; i++) if(dp[i]) ans++;printf("%d\n", ans);}return 0;}

poj 1276

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 100010;int dp[MAXN];int w[12], v[12];int cash;int queueid[MAXN];int queueval[MAXN];void complete(int V) {for(int i = V; i <= cash; i++)dp[i] = max(dp[i], dp[i - V] + V);}void zeroone(int V) {for(int i = cash; i >= V; i--)dp[i] = max(dp[i], dp[i - V] + V);}int main() {while(~scanf("%d", &cash)) {int n;scanf("%d", &n);memset(dp, 0, sizeof(dp));for(int i = 1; i <= n; i++) scanf("%d%d", &w[i], &v[i]);/*************************for(int i = 1; i <= n; i++) {if(w[i] * v[i] >= cash)complete(v[i]);else {int k = 1;while(k <= w[i]) {zeroone(k * v[i]);w[i] -= k;k *= 2;}zeroone(w[i] * v[i]);}}***********************/for(int i = 1; i <= n; i++) {if(w[i] * v[i] >= cash) complete(v[i]);else {for(int d = 0; d < v[i]; d++) {int st = 0, ed = -1;for(int j = d; j <= cash; j += v[i]) {if(ed >= st && (j - queueid[st]) / v[i] > w[i]) st++;while(ed >= st && queueval[ed] < dp[j] - (j - d)) ed--;queueid[++ed] = j;queueval[ed] = dp[j] - (j - d);dp[j] = queueval[st] + (j - d);}}}}printf("%d\n", dp[cash]);}return 0;}


0 0
原创粉丝点击