#include<iostream> #define rep(i, a, b) for(int i = (a); i <= (b); i ++ ) usingnamespace std; constint N = 1010; int n, m; int w[N][N]; int f[N][N]; int ans[N];
signedmain() { cin >> n >> m; rep(i, 1, n) rep(j, 1, m) cin >> w[i][j];
for(int i = 1; i <= n; i ++ ) for(int j = 0; j <= m; j ++ ) { f[i][j] = f[i - 1][j]; for(int k = 1; k <= m; k ++ ) if(j - k >= 0) f[i][j] = max(f[i][j], f[i - 1][j - k] + w[i][k]); }
cout << f[n][m] << endl;
int j = m; for(int i = n; i > 0; i -- ) { for(int k = 1; k <= m; k ++ ) { if(j - k >= 0 && f[i][j] == f[i - 1][j - k] + w[i][k]) { ans[i] = k; j -= k; break; } } }
for(int i = 1; i <= n; i ++ ) { cout << i << " " << ans[i] << endl; }
// 从方案数变成最优方案数, 需要再用一个dp维护使用前i个物品的最优方案数 #include<iostream> #include<algorithm> #include<cstring> #define rep(i, a, b) for(int i = (a); i <= (b); i ++ ) #define int long long usingnamespace std; constint N = 1010, mod = 1e9 + 7; int n, m; int v[N], w[N]; int f[N], g[N];
signedmain() { cin >> n >> m; rep(i, 1, n) cin >> v[i] >> w[i];
memset(f, -0x3f, sizeof f); f[0] = 0; g[0] = 1;
for(int i = 1; i <= n; i ++ ) for(int j = m; j >= v[i]; j -- ) { int ma = max(f[j], f[j - v[i]] + w[i]); int cnt = 0; if(ma == f[j]) cnt = g[j]; if(ma == f[j - v[i]] + w[i]) cnt += g[j - v[i]]; g[j] = cnt % mod; f[j] = ma; }
int ans = 0; rep(i, 0, m) ans = max(ans, f[i]); int cnt = 0; rep(i, 0, m) if(ans == f[i]) cnt += g[i]; cout << cnt % mod << endl;
#include<iostream> #define rep(i, a, b) for(int i = (a); i <= (b); i ++ ) #define int long long usingnamespace std; constint N = 1010, W = 6010; int n, m; int v[N], s[N], w[N]; int f[W];
#include<iostream> #include<cstring> #define rep(i, a, b) for(int i = (a); i <= (b); i ++ ) #define int long long usingnamespace std; constint N = 210; int n, m; int h[N], e[N], ne[N], idx; int v[N], w[N]; // 想选一定要选根节点, 所以无需担心不选中root的结果 int f[N][N]; // 根节点为u的子树, 且选中节点u, 总体积不超过j的最大价值
voidadd(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
voiddfs(int u) { for(int i = h[u]; i != -1; i = ne[i]) { int j = e[i]; dfs(j); // 先往里走把前置子树都更新完
// 每个子树做一次分组背包, 枚举当前子树不超过的体积[0, 100], 再枚举从该子树中选中多少体积 for(int x = m - v[u]; x >= 0; x -- ) for(int y = 0; y <= x; y ++ ) f[u][x] = max(f[u][x], f[u][x - y] + f[j][y]); // 子树体积不超过x, 从该子树选中y体积总和物品 }
// 我们假定一定要选中u, 将分组背包的结果加上u for(int i = m; i >= v[u]; i -- ) f[u][i] = f[u][i - v[u]] + w[u]; for(int i = 0; i < v[u]; i ++ ) f[u][i] = 0; }
signedmain() { cin >> n >> m; memset(h, -1, sizeof h);
int root; rep(i, 1, n) { int a, b, fa; cin >> a >> b >> fa; v[i] = a, w[i] = b; if(fa == -1) root = i; elseadd(fa, i); }