#include<iostream> #include<cstring> #include<algorithm> usingnamespacestd; constint N = 1010; int n, m; // 物品数量,背包容量 int v[N], w[N]; // 体积,价值 int f[N][N];
intmain(){ cin >> n >> m; for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i]; for (int i = 1; i <= n; i ++ ) // 物品 for (int j = 0; j <= m; j++) // 重量 for (int k = 0; k * v[i] <= j; k++) // 物品个数 f[i][j] = max(f[i][j], f[i-1][j-k*v[i]] + k*w[i]); cout << f[n][m] << endl; return0; }
#include<iostream> #include<cstring> #include<algorithm> usingnamespacestd; constint N = 1010; int n, m; int v[N], w[N]; int f[N][N];
intmain(){ cin >> n >> m; for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i]; for (int i = 1; i <= n; i ++ ) for (int j = 0; j <= m; j++) { if (j < v[i]) f[i][j] = f[i-1][j]; else f[i][j] = max(f[i-1][j], f[i][j-v[i]] + w[i]); } cout << f[n][m] << endl; return0; }
#include<iostream> #include<cstring> #include<algorithm> usingnamespacestd; constint N = 1010; int n, m; int v[N], w[N]; int f[N];
intmain(){ cin >> n >> m; for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i]; for (int i = 1; i <= n; i ++ ) for (int j = v[i]; j <= m; j++) // 从小到大循环 f[j] = max(f[j], f[j-v[i]] + w[i]); cout << f[m] << endl; return0; }
#include<iostream> #include<cstring> #include<algorithm> usingnamespacestd; constint N = 1010; int n, m; int f[N];
intmain(){ cin >> n >> m; for (int i = 1; i <= n; i ++ ) { int v, w; cin >> v >> w; for (int j = v; j <= m; j++) f[j] = max(f[j], f[j-v] + w); } cout << f[m] << endl; return0; }
#include<iostream> #include<cstring> #include<algorithm> usingnamespacestd; constint N = 110; int v[N], w[N], s[N]; int f[N][N]; int n, m;
intmain(){ cin >> n >> m; for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i] >> s[i]; for (int i = 1; i <= n; i ++ ) for (int j = 0; j <= m; j++) for (int k = 0; k <= s[i] && k * v[i] <= j; k++) f[i][j] = max(f[i][j], f[i-1][j-v[i]*k] + w[i]*k); cout << f[n][m] << endl; return0; }
#include<iostream> #include<algorithm> usingnamespacestd; // 当有1000种物品,每种物品的数量为2000,得25000 constint N = 25000; // 留意开辟空间 int f[N]; int v[N], w[N]; int n, m;
intmain(){ cin >> n >> m; int cnt = 0; for (int i = 1; i <= n; i++) { int a, b, s; cin >> a >> b >> s; // 二进制优化核心代码 int k = 1; while (k <= s) { cnt++; v[cnt] = a * k; w[cnt] = b * k; s -= k; k *= 2; } if (s > 0) { cnt++; v[cnt] = a * s; w[cnt] = b * s; } } n = cnt; // 0-1背包 for (int i = 1; i <= n; i++) for (int j = m; j >= v[i]; j--) f[j] = max(f[j], f[j-v[i]] + w[i]); cout << f[m] << endl; return0; }
for (int len = 1; len <= n; len++) { // 区间长度 for (int i = 1; i + len - 1 <= n; i++) { // 枚举起点 int j = i + len - 1; // 区间终点 if (len == 1) { f[i][j] = 初始值 continue; }
for (int k = i; k < j; k++) { // 枚举分割点,构造状态转移方程 f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + w[i][j]); } } }
#include<iostream> #include<algorithm> usingnamespacestd; constint N = 310; int n; int f[N][N]; int s[N];
intmain(){ scanf("%d", &n); for (int i = 1; i <= n; i ++ ) scanf("%d", &s[i]); // 前缀和,确定任一区间的权重 for (int i = 1; i <= n; i ++ ) s[i] += s[i-1]; // len=1的时候无须合并,所以从2开始 for (int len = 2; len <= n; len++) // 区间长度 for (int i = 1; i + len - 1 <= n; i++) {// 枚举起点 int l = i, r = i + len -1; f[l][r] = 1e8; // 在区间范围内进行划分 for (int k = l; k < r; k++) // 不能取等,要保证右边至少有一个才有得合并 f[l][r] = min(f[l][r], f[l][k] + f[k+1][r] + s[r] - s[l-1]); } cout << f[1][n] << endl; return0; }
#include<iostream> #include<string.h> #include<algorithm> usingnamespacestd; constint N = 1010; char str[N]; int f[N][N];
intmain(){ scanf("%s", str); int n = strlen(str); for (int len = 1; len <= n; len++) { for (int l = 0; l + len - 1 < n; l++) { int r = l + len - 1; if (l == r) f[l][r] = 1; else { if (str[l] == str[r]) f[l][r] = f[l+1][r-1] + 2; if (f[l+1][r] > f[l][r]) f[l][r] = f[l+1][r]; if (f[l][r-1] > f[l][r]) f[l][r] = f[l][r-1]; } } } cout << n - f[0][n-1] << endl; return0; }
#include<iostream> #include<algorithm> #include<vector> usingnamespacestd; int a, b;
// 求10^x intpower10(int x){ int res = 1; while (x--) { res *= 10; } return res; }
// 将num中l到r表示的数提取成一个数 intget(vector<int> num, int l, int r){ int res = 0; for (int i = l; i >= r; i--) { res = res * 10 + num[i]; } return res; }
// 数位DP intcount(int n, int x){ // 1到0中不含有任何数 if (!n) return0; vector<int> num; // 将n倒序存放 while (n) { num.push_back(n % 10); n /= 10; } // 获取n的位数,用于遍历 n = num.size(); int res = 0; // 遍历x在n的每一位上出现的次数,并作和 // 若x为0,则x必不出现在n的最高位,直接从第二位开始计算 for (int i = n - 1 - !x; i >= 0; i--) { // 枚举在第i位上,x出现的次数 // 情况一 if (i < n - 1) { res += get(num, n-1, i+1) * power10(i); if (!x) res -= power10(i); } // 情况二 if (num[i] == x) res += get(num, i-1, 0) + 1; elseif (num[i] > x) res += power10(i); } return res; } // 暴力解法 intforce_count(int n, int x){ int res = 0; for (int i = 1; i <= n; i++) for (int j = i; j; j /= 10) if (j % 10 == x) res++; return res; } intmain(){ while (cin >> a >> b, a || b) { if (a > b) swap(a, b); for(int i = 0; i < 10; i++) { // 以前缀和的方式,求ab区间i出现的次数 cout << count(b, i) - count(a-1, i) << ' '; } cout << endl; } return0; }
#include<iostream> #include<algorithm> #include<cstring> usingnamespacestd; constint N = 6010; int n; int h[N], e[N], ne[N], idx; int happy[N]; bool st[N]; int f[N][2]; // 树形DP
voidadd(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
voiddfs(int u){ f[u][1] = happy[u]; for (int i = h[u]; i != -1; i = ne[i]) { int j = e[i]; dfs(j); // 上司不去舞会 f[u][0] += max(f[j][0], f[j][1]); // 上司去舞会 f[u][1] += f[j][0]; } }
intmain(){ cin >> n; for (int i = 1; i <= n; i++) cin >> happy[i]; memset(h, -1, sizeof h); for (int i = 0; i < n-1; i++) { int a, b; cin >> a >> b; st[a] = true; add(b, a); } int root = 1; while(st[root]) root++; dfs(root); cout << max(f[root][0], f[root][1]) << endl; return0; }
#include<iostream> #include<cstring> #include<algorithm> usingnamespacestd; constint N = 2e5 + 10, M = 2 * N; int h[N], e[M], w[M], ne[M], idx; int down[N], up[N]; int n; // 数组模拟邻接表 voidadd(int a,int b, int c){ // a->b e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; } // 当前节点向下搜 voiddfs_down(int u, int from){ // from为边的编号,容易求出反向边 for (int i = h[u]; ~i; i = ne[i]) { if (i == (from ^ 1)) continue; // 边是双向的,避免往回搜,出现死循环 int j = e[i]; dfs_down(j, i); down[u] += down[j] + w[i]; } } // 当前节点往上搜 voiddfs_up(int u, int from){ if (from != -1) { int fa = e[from ^ 1]; // 反向边的终点 up[u] = up[fa] + down[fa] - down[u] - w[from] + w[from^1]; } for (int i = h[u]; ~i; i = ne[i]) { if (i == (from ^ 1)) continue; int j = e[i]; dfs_up(j, i); } }
intmain(){ scanf("%d", &n); memset(h, -1, sizeof h); for (int i = 0; i < n - 1; i++) { int a, b; scanf("%d%d", &a, &b); add(a, b, 0); add(b, a, 1); } dfs_down(1, -1); dfs_up(1, -1); int res = N; for (int i = 1; i <= n; i++) res = min(res, down[i] + up[i]); printf("%d\n", res); for (int i = 1; i <= n; i++) if (down[i] + up[i] == res) printf("%d ", i); return0; }
#include<iostream> #include<cstring> usingnamespacestd; typedeflonglong LL; constint N = 1e5 + 10, M = 2*N; int n; int h[N], e[M], ne[M], idx; int w[N]; LL f[N]; // 树形DP
voidadd(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
voiddfs(int u, int fa){ f[u] = w[u]; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (j == fa) continue; dfs(j, u); // 往下搜j点,并记录上一个点为u f[u] += max(0ll, f[j]); } }
intmain(){ scanf("%d", &n); memset(h, -1, sizeof h); for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]); for (int i = 0; i < n - 1; i++) { int a, b; scanf("%d%d", &a, &b); add(a, b), add(b, a); } dfs(1, -1); LL res = f[1]; for (int i = 2; i <= n; i++) res = max(res, f[i]); printf("%lld\n", res); return0; }
intdp(int x, int y){ // 引用:v相当于f[x][y] int &v = f[x][y]; // 利用了记忆化搜索过程中的结果 if (v != -1) return v; // 无格可走,最小为1 v = 1; for (int i = 0; i < 4; i++) { int a = x + dx[i], b = y + dy[i]; if (a >= 1 && a <= n && b >= 1 && b <= m && h[a][b] < h[x][y]) // 记忆化搜索 v = max(v, dp(a, b) + 1); } return v; }
intmain(){ cin >> n >> m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) cin >> h[i][j]; // 读入高度 // 初始化状态为-1 memset(f, -1, sizeof f); int res = 0; // 枚举每一个点,取最大值 for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) res = max(res, dp(i, j)); cout << res << endl; return0; }