memset(f, 0, sizeof(f)); for (int k = 2; k <= 2 * n; k ++ ) for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= n; j ++ ){ if (k - i < 1 || k - i > n || k - j < 1 || k - j > n) continue;
int t = w[i][k - i]; if (i != j) t += w[j][k - j]; for (int u = 0; u < 4; u ++ ) f[k][i][j] = max(f[k][i][j], f[k - 1][i + dx[u]][j + dy[u]] + t); } cout << f[2 * n][n][n] << endl;
int res = -INF for (int i = 0; i < n; i ++ ){ f[i] = w[i]; for (int j = 0; j < i; j ++ ) if (w[i] > w[j]) f[i] = max(f[i], f[j] + w[i]); res = max(res, f[i]); } cout << res << endl;
int res = 0; for (int i = 1; i <= n; i ++ ){ int tmp = 1; for (int j = 1; j <= n; j ++ ){ f[i][j] = f[i - 1][j]; if (a[i] > b[j]) tmp = max(tmp, f[i - 1][j] + 1); if (a[i] == b[j]) f[i][j] = max(f[i][j], tmp); if (i == n) res = max(res, f[i][j]); } } cout << res << endl;
背包模型
有背包体积$m$,$n$个待决策的物品,每个物品对应有体积$v_i$、价值$w_i$,
对每个物品的决策可能是:选择加入背包、选择不加入背包,
求,对于所有决策可能,背包(中各个物品的集体)的最大价值。
1 2 3 4 5 6 7 8 9 10 11 12 13
int n, m; int v[N], w[N]; // 1 ~ n int f[N][M]; // (1 ~ n, 0 ~ m)
for (int i = 0; i <= m; i ++ ) f[0][i] = 0;
for (int i = 1; i <= n; i ++ ) for (int j = 0; j <= m; j ++ ){ f[i][j] = f[i - 1][j]; if (j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]); }
cout << f[n][m] << endl;
费用情况
以求方案数为例:
限定费用上限;
1 2 3 4 5 6 7
for (int i = 0; i <= m; i ++ ) f[0][i] = 1;
for (int i = 1; i <= n; i ++ ) 4for (int j = 0; j <= m; j ++ ){ f[i][j] = f[i - 1][j]; if (j >= v[i]) f[i][j] += f[i - 1][j - v[i]]; }
限定费用为定值;
1 2 3 4 5 6 7 8
for (int i = 1; i <= m; i ++ ) f[0][i] = 0; f[0][0] = 1;
for (int i = 1; i <= n; i ++ ) 4for (int j = 0; j <= m; j ++ ){ f[i][j] = f[i - 1][j]; if (j >= v[i]) f[i][j] += f[i - 1][j - v[i]]; }
限定费用下限;
1 2 3 4 5 6 7 8
for (int i = 1; i <= m; i ++ ) f[0][i] = 0; f[0][0] = 1;
for (int i = 1; i <= n; i ++ ) for (int j = 0; j <= m; j ++ ){ f[i][j] = f[i - 1][j]; f[i][j] += f[i - 1][max(0, j - v[i])]; }
购买次数
各物品均限购一次;
1 2 3 4 5
for (int i = 1; i <= n; i ++ ) for (int j = 0; j <= m; j ++ ){ f[i][j] = f[i - 1][j]; if (j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]); }
for (int i = 1; i <= n; i ++ ) 4for (int j = m; j >= v; j -- ) f[j] = max(f[j], f[j - v[i]] + w[i]);
cout << f[m] << endl;
二维费用
1 2 3 4
for (int i = 1; i <= n; i ++ ) for (int j = V1; j >= v1[i]; j -- ) for (int k = V2 - 1; k >= v2[i]; k -- ) f[j][k] = max(f[j][k], f[j - v1[i]][k - v2[i]] + w[i]);
具体方案
物品维从大到小递推,求方案时就能从小到大反推,并且能选则选,即可得字典序最小方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
for (int i = n; i >= 1; i -- ) for (int j = 0; j <= m; j ++ ){ f[i][j] = f[i + 1][j]; if (j >= v[i]) f[i][j] = max(f[i][j], f[i + 1][j - v[i]] + w[i]); }
int p = m; bool flag = false; for (int i = 1; i <= n; i ++ ) if (p >= v[i] && f[i][p] == f[i + 1][p - v[i]] + w[i]){ if (!flag){ cout << i; flag = true; } else cout << ' ' << i; p -= v[i]; } cout << endl;
int res = 0; m = a[n]; memset(f, 0, sizeof(f)); f[0] = true; for (int i = 1; i <= n; i ++ ){ if (!f[a[i]]) res ++ ; for (int j = a[i]; j <= m; j ++ ) f[j] |= f[j - a[i]]; } printf("%d\n", res);
while (n -- ){ int v, w, s; cin >> v >> w >> s; if (s == 0){ for (int j = v; j <= m; j ++ ) f[j] = max(f[j], f[j - v] + w); } else{ if (s == - 1) s = 1; for (int k = 1; k <= s; k <<= 1){ for (int j = m; j >= k * v; j -- ) f[j] = max(f[j], f[j - k * v] + k * w); s -= k; } if (s){ for (int j = m; j >= s * v; j -- ) f[j] = max(f[j], f[j - s * v] + s * w); } } } cout << f[m] << endl;
voiddfs(int u){ for (int i = h[u]; ~i; i = ne[i]){ int son = e[i]; dfs(son); memcpy(g, f, sizeof(f)); for (int j = 0; j <= m - v[u]; j ++ ) for (int k = 0; k <= j; k ++ ) // 相当于分组背包的决策层,以所分配的体积作决策 f[u][j] = max(f[u][j], g[u][j - k] + f[son][k]); } memcpy(g, f, sizeof(f)); for (int i = 0; i <= m; i ++ ) if (i < v[u]) f[u][i] = 0; else f[u][i] = g[u][i - v[u]] + w[u]; }
int n; structNode{ int s, e, l; booloperator<(const Node &W)const{ return s * W.l < W.s * l; } }p[N]; int f[M];
intmain(){ int T; scanf("%d", &T); for (int C = 1; C <= T; C ++ ){ scanf("%d", &n); int m = 0; for (int i = 1; i <= n; i ++ ){ scanf("%d %d %d", &p[i].s, &p[i].e, &p[i].l); m += p[i].s; } sort(p + 1, p + n + 1); memset(f, -0x3f, sizeof(f)); f[0] = 0; for (int i = 1; i <= n; i ++ ) for (int j = m; j >= p[i].s; j -- ) f[j] = max(f[j], f[j - p[i].s] + p[i].e - (j - p[i].s) * p[i].l); int res = 0; for (int i = 0; i <= m; i ++ ) res = max(res, f[i]); printf("Case #%d: %d\n", C, res); } return0; }
int n, m; PII mas[N]; vector<PII> ser[N]; int f[M];
intmain(){ cin >> m >> n; for (int i = 1; i <= n; i ++ ){ int v, w, p; cin >> v >> w >> p; if (!p) mas[i] = {v, v * w}; else ser[p].push_back({v, v * w}); } for (int i = 1; i <= n; i ++ ) for (int j = m; j >= 0; j -- ){ int sz = ser[i].size(); for (int k = 0; k < 1 << sz; k ++ ){ int v = mas[i].v, w = mas[i].w; for (int u = 0; u < sz; u ++ ) if (k >> u & 1){ v += ser[i][u].v; w += ser[i][u].w; } if (j >= v) f[j] = max(f[j], f[j - v] + w); } } cout << f[m] << endl; return0; }
memset(f, -0x3f, M * 2 * 4); for (int i = 0; i <= n - 1; i ++ ) f[i][0][0] = 0; for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= m; j ++ ){ f[i][j][0] = max(f[i - 1][j][0], f[i - 1][j][1] + a[i]); f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - a[i]); } int res = 0; for (int i = 0; i <= m; i ++ ) res = max(res, f[n][i][0]); cout << res << endl;