当前位置:   article > 正文

DP经典问题---背包问题的代码实现(入门级)(C++/PYTHON)_c++背包dp

c++背包dp
背包的状态转换方程

i:表示物品序号

j:表示背包大小

W [i]:表示第i件物品的重量

f[i,j]:表示在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值

f[i-1,j-Wi]:表示在前i-1件物品中选择若干件放在承重为j-Wi的背包中,可以取得的最大价值

Pi(j>=Wi):表示第i件物品的价值,要求背包大小j要大于此件物品的重量

f[i-1,j]:表示前i-1件物品中选择若干件放在承重为j的背包中,可以取得的最大价值

1.01背包问题2. 01背包问题 - AcWing题库

首先我们创立两个一维数组,用来存储大小和价值

再创立一个二维数组用来状态分析

分析背包问题我们是曲线救国,调用已经存在的数据元素来解决问题

物品个数是从1到n,然后分别得出该个数下的最大价值

我们要分析两个状态,放与不放,

第一种--不放i物品:f[i][j]=f[i-1][j](调用的是i-1状态下的最大值)

第二种--放i物品:f[i][j]=f[i-1] [j-v[i]] + w[i](此时同时是调用i-1个物品下的状态,

但是此时放物品那你要留空给这个物品放,so,此时调用的状态转移方程容量是j-v[i]条件下的,

最后再加上w[i]就是该状态下的value了)(当然,背包的容量要大于v[i]要不然放不下i 物品)

last but not least,我们要对两种状态,放与不放的价值大小进行判断

f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i])

最后输出则可。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=1010;
  4. int main(){
  5. int n,m;
  6. int v[N],w[N];
  7. int f[N][N];
  8. cin>>n>>m;
  9. for (int i=1;i<=n;i++) cin>>v[i]>>w[i];
  10. for (int i=1;i<=n;i++)//物品个数 1-n
  11. for (int j=0;j<=m;j++){//容量 0-m
  12. f[i][j]=f[i-1][j];//先赋值给不放第i个,在下面再比较放与不妨
  13. if (j>=v[i]) f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);//f[i][j]= (1) f[i-1][j] (2) f[i-1][j-v[i]]+w[i]
  14. //第一种情况是取的是i-1个物品的最大 容量为j
  15. //第二种是[i-1]个但是把第i个放入的情况,那要取的是【i-1】,但是其内存要是j-v[i]--相当于留了一个地方存这个物品,取得是之前的最后再加上w[i]成为新的f[i][j]
  16. }
  17. cout<<f[n][m]<<endl;
  18. return 0;
  19. }
  1. n,m=map(int,input().split())#n是物品,m是容量
  2. v=[]#容量
  3. w=[]#价值
  4. v.append(0)
  5. w.append(0)
  6. f=[[0 for j in range(n+m)] for i in range(m+n)]
  7. for i in range(n):
  8. a,b=map(int,input().split())
  9. v.append(a)
  10. w.append(b)
  11. for i in range(1,n+1):
  12. for j in range(0,m+1):
  13. f[i][j]=f[i-1][j]
  14. if j>=v[i]:
  15. f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i])
  16. print(f[n][m])

2.完全背包问题3. 完全背包问题 - AcWing题库

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=1010;
  4. int v[N],w[N];
  5. int f[N][N];
  6. int n,m;
  7. int main()
  8. {
  9. cin>>n>>m;
  10. for (int i=1;i<=n;i++) cin>>v[i]>>w[i];
  11. for (int i=1;i<=n;i++)
  12. for (int j=0;j<=m;j++)
  13. for (int k=0;k*v[i]<=j;k++)
  14. f[i][j] = max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
  15. cout<<f[n][m]<<endl;
  16. return 0;
  17. }
  1. n, m = map(int, input().split())
  2. v, w = [0] * (n + 1), [0] * (n + 1)
  3. for i in range(1, n + 1):
  4. v[i], w[i] = map(int, input().split())
  5. # 二维:
  6. # 状态表示f[i][j] 选择前i个物品,总体积小于等于j的最大价值
  7. # 状态计算f[i][j] = max(f[i-1][j], f[i][j - v[i] + w[i] if j >= v[i])
  8. # 物品种类不限,所以max中第二项和0-1背包不同
  9. f = [[0] * (m + 1) for _ in range(n + 1)]
  10. for i in range(1, n + 1):
  11. for j in range(m + 1):
  12. f[i][j] = f[i-1][j]
  13. if j >= v[i]:
  14. f[i][j] = max(f[i][j], f[i][j-v[i]] + w[i])
  15. print(max(f[n]))
  1. n, m = map(int, input().split())
  2. v, w = [0] * (n + 1), [0] * (n + 1)
  3. for i in range(1, n + 1):
  4. v[i], w[i] = map(int, input().split())
  5. # 一维:f[j] 代表总体积小于等于j的最大价值
  6. # 因为每种物品数量不限,所以j从小到大更新,即可以使用前面当前层j更新后的结果
  7. f = [0] * (m + 1)
  8. for i in range(1, n + 1):
  9. for j in range(v[i], m + 1):
  10. f[j] = max(f[j], f[j-v[i]] + w[i])
  11. print(f[m])

3.多重背包问题4. 多重背包问题 I - AcWing题库

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=110;
  4. int v[N],w[N],s[N];
  5. int f[N][N];
  6. int main()
  7. {
  8. int n,m;
  9. cin>>n>>m;
  10. for (int i=1;i<=n;i++) cin>>v[i]>>w[i]>>s[i];
  11. for (int i=1;i<=n;i++)
  12. for (int j=0;j<=m;j++){
  13. for(int k=0;k<=s[i] && k*v[i]<=j;k++)
  14. {
  15. f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+w[i]*k);
  16. }
  17. }
  18. cout<<f[n][m]<<endl;
  19. return 0;
  20. }
  1. n,v = map(int, input().split())
  2. goods = []
  3. for i in range(n):
  4. goods.append([int(i) for i in input().split()])
  5. new_goods = []
  6. for i in range(n):
  7. for j in range(goods[i][2]):
  8. new_goods.append(goods[i][0:2])
  9. goods = new_goods
  10. n = len(goods)
  11. dp = [0 for i in range(v+1)]
  12. for i in range(n):
  13. for j in range(v,-1,-1):
  14. if j>= goods[i][0]:
  15. dp[j] = max(dp[j], dp[j - goods[i][0]] + goods[i][1])
  16. print(dp[-1])

4.数字三角形3304. 数字三角形 - AcWing题库

数字三角形属于线性DP问题。状态表示也是一个2维数组,f[i][j],i,j分别表示行与列

状态分析同时也是f[i][j]调用已经存在的状态值,该题的f[i][j]可以由两个方向过来,左上右上,

左上:f[i-1][j-1]+a[i][j]

右上:f[i-1][j]+a[i][j]

f [i][j]=max ( f [i-1] [j-1] + a[i] [j] , f [i-1] [j] + a[i] [j])

数字三角形题目还需注意左右次数的问题。

  1. #include<iostream>
  2. using namespace std;
  3. const int N = 510 , M = -1e9;;
  4. int n;
  5. int a[N][N];
  6. int f[N][N];
  7. int main(){
  8. cin >> n;
  9. for(int i = 1; i <= n; i++){
  10. for(int j = 1; j <= i; j++){
  11. cin >> a[i][j];
  12. }
  13. }
  14. for(int i = 0; i <= n; i++){
  15. for(int j = 0; j <= i+1; j++){
  16. //注意这里的循环判断条件 从零开始到最后一个数字的后一个位置都要初始化,因为他会用到左边界和右边界上的值.
  17. f[i][j] = M;
  18. }
  19. }
  20. f[1][1] = a[1][1];
  21. for(int i = 2; i <= n; i++){
  22. //前面第一个位置只有一种情况,所以从2开始
  23. for(int j = 1; j <= i; j++){
  24. f[i][j] = max(f[i-1][j-1]+a[i][j], f[i-1][j]+a[i][j]);
  25. }
  26. }
  27. if (n % 2 == 0) cout << max(f[n][n / 2], f[n][n / 2 + 1]) << '\n';
  28. else cout << f[n][n / 2 + 1];
  29. return 0;
  30. }
  1. n=int(input())
  2. arrs=[[0 for i in range(1,n+1+1)] for i in range(n+1)]#存数的数组
  3. arr=[[0 for i in range(1,n+3)] for i in range(n+1)]#动态规划状态调用数组
  4. for i in range(1,n+1):
  5. arrs[i][1:n]=list(map(int,input().split()))
  6. arr[1][1] =arrs[1][1]
  7. for i in range(2,n+1):
  8. for j in range(1,i+1):
  9. arr[i][j]=max(arr[i-1][j-1]+arrs[i][j],arr[i-1][j]+arrs[i][j])
  10. if n % 2 == 1:
  11. print(arr[-1][n//2 + 1])
  12. else:
  13. print(max(arr[-1][n//2],arr[-1][n//2+1]))

注:作者一些题目的解法可能并不是最优解,可以就行指出探讨。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/961623
推荐阅读
相关标签
  

闽ICP备14008679号