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 = m; j >= v[i]; j--) //从后向前更新 { // f[j] = f[j]; f[j] = max(f[j], f[j - v[i]] + w[i]); } cout << f[m] << ' '; return0; }
python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
n,k = map(int,input().split())
dp = [[0]*(k+10) for _ inrange(n+10)] v = [0] * (n+10) w = [0] * (n+10) for i inrange(1,n+1): a,b = map(int,input().split()) v[i] = a w[i] = b
for i inrange(1,n+1): for j inrange(1,k+1): dp[i][j] = dp[i-1][j] #继承状态,不取第i个物品 if v[i] <= j: dp[i][j] = max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]) #第i个物品只能取一次 print(dp[n][k])
滚动数组写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
n,k = map(int,input().split())
dp = [0]*(k+10) v = [0] * (n+10) w = [0] * (n+10) for i inrange(1,n+1): a,b = map(int,input().split()) v[i] = a w[i] = b
for i inrange(1,n+1): for j inrange(k,v[i]-1,-1): # 注意range循环左闭右开的特性,应为v[i]-1 dp[j] = max(dp[j],dp[j-v[i]]+w[i]) print(dp[k])
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++) //正序更新,依赖于当前f[i]层的数据 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]); //与01背包思想差不多
v = [0]*(n+10) w = [0]*(n+10) dp = [[0]*(m+10) for _ inrange(n+10)]
for i inrange(1,n+1): v[i],w[i] = map(int,input().split()) for i inrange(1,n+1): for j inrange(1,m+1): for k inrange(0,j+1): if k*v[i]>j: break dp[i][j] = max(dp[i][j],dp[i-1][j-k*v[i]]+ k*w[i]) # print(dp[n][m])
for i inrange(1,n+1): v[i],w[i] = map(int,input().split()) for i inrange(1,n+1): for j inrange(0,m+1): if j < v[i]: #若不加这句,程序能正常运行但答案错误,因为python支持负索引 continue dp[j] = max(dp[j],dp[j-v[i]]+w[i]) print(dp[m])
v = [0]*(n+10) w = [0]*(n+10) c = [0]*(n+10) dp = [[0]*(m+10) for _ inrange(n+10)]
for i inrange(1,n+1): v[i],w[i],c[i] = map(int,input().split()) for i inrange(1,n+1): for j inrange(1,m+1): for k inrange(0,c[i]+1): if j < v[i]*k: continue dp[i][j] = max(dp[i][j],dp[i-1][j-v[i]*k] + w[i]*k) print(dp[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; // 体积:原始体积 a 乘以 k w[cnt] = b * k; // 价值:原始价值 b 乘以 k s -= k; // 减去已经处理的数量 k *= 2; // 乘以 2,进入下一个更大的子背包 } if (s > 0) // 剩余部分作为一个小背包处理 { cnt++; v[cnt] = a * s; w[cnt] = b * s; } } //转化为01背包问题 n = cnt; 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]);
intmain() { cin >> n >>m; for (int i = 1; i <= n; i ++) { cin >> s[i]; for (int j = 1; j <= s[i]; j ++) cin >> v[i][j] >> w[i][j]; }
for (int i = 1; i <= n; i ++ ) //枚举所有组 for (int j = m; j >= 0; j --) //枚举所有背包组 for (int k = 1; k <= s[i]; k ++ ) //枚举组内对象 if (v[i][k] <= j) f[j] = max(f[j], f[j-v[i][k]] + w[i][k]);
tot = [0]*105 v = [[0]*(105) for _ inrange(n+10)] w = [[0]*(105) for _ inrange(n+10)] for i inrange(1,n+1): nn = int(input()) tot[i] = nn for j inrange(1,nn+1): a,b = map(int,input().split()) v[i][j] = a w[i][j] = b for i inrange(1,n+1): for j inrange(m,-1,-1): for k inrange(1,tot[i]+1): if j < v[i][k]: continue dp[j] = max(dp[j],dp[j-v[i][k]] + w[i][k])
usingnamespace std; constint N = 100010; int n; int a[N]; int q[N];
intmain() { cin >> n;
for (int i = 0; i < n; i ++ ) cin >> a[i]; int len = 0; for (int i = 0; i < n; i ++ ) { int l = 0, r = len; while( l < r) { int mid = (l + r + 1) >> 1; if( q[mid] < a[i] ) //保证是最大小于a[i]的位置,并覆盖q[r+1] l = mid; else r = mid - 1; } len = max(len, r + 1); q[r + 1] = a[i]; } printf("%d\n", len); return0; }
n = int(input()) a = " " + input().strip() m = int(input()) b = " " + input().strip() f = [[0] * (m + 1) for _ inrange(n + 1)] for i inrange(n + 1): f[i][0] = i #令前i个字符串变成0空串,需要i步 for j inrange(m + 1): f[0][j] = j #令空串变成前i个字符串,需要i步
dp = [[0]*13for _ inrange(13)] #要加入0才是整型数组 defjudge(n1): ss = strb[n1] res = 0 for i inrange(n): sss = stra[i] for j inrange(12): #print(1) dp[0][j] = j for j inrange(12): dp[j][0] = j for j inrange(1,len(sss)): for k inrange(1,len(ss)): dp[j][k] = min(dp[j][k-1]+1,dp[j-1][k]+1) if sss[j] == ss[k]: dp[j][k] = min(dp[j][k],dp[j-1][k-1]) else: dp[j][k] = min(dp[j][k],dp[j-1][k-1]+1) if dp[len(sss)-1][len(ss)-1] <= cnt[n1]: res += 1 print(res) for i inrange(m): judge(i)
for i inrange(1,n+1): #前缀和 brr[i] = arr[i] + brr[i-1] forleninrange(2,n+1): #枚举合并大小 for j inrange(1,n-len+1+1): #枚举合并的起始位置 l = j r = j+len-1 dp[l][r] = 0x3f3f3f3f for k inrange(l,r): dp[l][r] = min(dp[l][r],dp[l][k]+dp[k+1][r] + brr[r] - brr[l-1])
intget(int x){ int res = 0; while (x) res++, x /= 10; return res; }
intcount(int n, int i){ int res = 0, dgt = get(n); for (int j = 1; j <= dgt; ++j) { // p为当前遍历位次数大小 // l为第j位的左边的数 // r为右边的数 // dj为第j位上的数 int p = pow(10, dgt - j); int l = n/p/10; int r = n % p; int dj = n / p % 10;
if (i == dj) res += r + 1; //等于需小于等于r if (i < dj) res += p; //小于可取全部值 //大于则无
} return res; }
intmain(){ int a, b; while (cin >> a >> b, a) { // 输入处理,直到输入为0 0停止 if (a > b) swap(a, b); for (int i = 0; i <= 9; ++i) cout << count(b, i) - count(a - 1, i) << ' '; //输出各位数字的个数 //利用前缀和思想:[l,r]的和=s[r] - s[l - 1] cout << endl; }
#include<iostream> #include<algorithm> #include<cstring> usingnamespace std; constint N = 310; int n,m; int f[N][N]; int h[N][N]; int dx[4] = {-1,0,1,0}; int dy[4] = {0,1,0,-1};
intdp(int x, int y){ int &v = f[x][y]; if(v != -1) return v; v = 1; //注意v要先赋值为1哦~ for(int i = 0;i < 4;i ++){ //四个方向 int xx = x + dx[i]; int yy = y + dy[i]; if(xx >= 1 && xx <= n && yy >= 1 && yy <= m && h[x][y] > h[xx][yy]){ //判断这点是否能走 v = max(v,dp(xx,yy) + 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]; } } 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; }