0-1背包问题(动态规划) 解题报告

本文介绍了解决0-1背包问题的一种动态规划方法。通过自底向上的方式,逐步解决子问题,最终得出最优解。文章提供了一个完整的C++实现代码示例,包括输入物品价值和重量、求解最大价值及输出最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用动态规划,以自底向上的方式解各子问题。

解题思路:此问题可转化为:给定c>0,wi>0,vi>0,1≤i≤n,要求找出一

个n元0-1向量(x1,x2,…,xn),xi∈{0,1},1≤i≤n,使得∑wixi≤c,而且

∑vixi达到最大。因此,0-1背包是一个特

殊的整数规划问题:

max ∑vixi
s.t. ∑wixi≤c
xi∈{0,1},1≤i≤n
代码如下:
Code:
  1. #include<iostream>
  2. #include<iomanip>
  3. #include<string>
  4. usingnamespacestd;
  5. intMin(intw,intc)//取较小值
  6. {
  7. return(w<c?w:c);
  8. }
  9. intMax(intw,intc)//取较大值
  10. {
  11. return(w<c?c:w);
  12. }
  13. voidKnapsack(intv[],intw[],intc,intn,int**m)
  14. {
  15. intrange1=Min(w[n]-1,c);
  16. for(intj=0;j<=range1;j++)//如果物品的重量超过负重就都复制为0
  17. m[n][j]=0;
  18. for(j=w[n];j<=c;j++)//对于可以放的
  19. m[n][j]=v[n];
  20. for(inti=n-1;i>1;i--)//从下往上
  21. {
  22. range1=Min(w[i]-1,c);
  23. for(j=0;j<=range1;j++)//如果物品的重量超过负重则不加入
  24. m[i][j]=m[i+1][j];
  25. for(intrange2=w[i];range2<=c;range2++)
  26. m[i][range2]=Max(m[i+1][range2],m[i+1][range2-w[i]]+v[i]);//放与不放中取较大值
  27. }
  28. m[1][c]=m[2][c];//对第一个物品进行处理
  29. if(c>=w[1])
  30. m[1][c]=Max(m[1][c],m[2][c-w[1]]+v[1]);
  31. cout<<"最优解:"<<m[1][c]<<endl;
  32. }
  33. voidPrint_Case(int**m,intw[],intc,intn,intx[])//输出物品存放的情况
  34. {
  35. cout<<"得到的一组最优解如下:"<<endl;
  36. for(inti=1;i<n;i++)
  37. if(m[i][c]==m[i+1][c])
  38. x[i]=0;
  39. else
  40. {
  41. x[i]=1;
  42. }
  43. x[n]=(m[n][c])?1:0;
  44. for(inty=1;y<=n;y++)
  45. {
  46. cout<<setw(5)<<x[y];
  47. }
  48. cout<<endl;
  49. return;
  50. }
  51. voidmain()
  52. {
  53. intn,c;
  54. int**m;
  55. cout<<"请输入物品的个数以及重量的上限:";
  56. cin>>n>>c;
  57. int*v=newint[n+1];
  58. cout<<"请输入物品的价值(v[i]:)"<<endl;
  59. for(inti=1;i<=n;i++)
  60. cin>>v[i];
  61. int*w=newint[n+1];
  62. cout<<"请输入物品的重量(w[i]):"<<endl;
  63. for(intj=1;j<=n;j++)
  64. cin>>w[j];
  65. int*x=newint[n+1];
  66. m=newint*[n+1];
  67. for(intp=0;p<n+1;p++)
  68. {
  69. m[p]=newint[c+1];
  70. }
  71. Knapsack(v,w,c,n,m);
  72. Print_Case(m,w,c,n,x);
  73. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值