0-1背包问题笔记

来源:互联网 发布:js文件压缩成 min.js 编辑:程序博客网 时间:2024/05/21 21:35

0-1背包问题

2 2 6 5 4

6 3 5 4 6

C[i][j]=max{C[i-1][j],C[i-1][j-wi]+vi} j>=wi这一步就是考虑将该物品可以装入的情况下,是否可以是一定质量下价值最大  就是判断在抉择某一物品时,重量从0到W的最佳抉择方案

或者

C[i][j]=C[i-1][j] j<wi因为达不到那个重量,所以不可能装入该物品,所以此物品没有被装入

以上这个公式非常重要,要是通过这个公式理解了挑选物品的规划过程,0-1背包问题就理解了。

当i从1开始到n-1的过程中,不断的探索C[i][j](0<=j<=W)的值,选出一个最优值。

当j从0到W的变化过程中,探索不同重量能获得的价值。

我觉得最妙的地方在于,它会从该物品放入或者没有放入两种情况中选择一种最优值放入。

    0  1  2  3  4  5  6  7  8  9  100  0  0  0  0  0  0  0  0  0  0  0
1  
2
3
4
5代码如下:

#include <iostream>using namespace std;struct Weight_Value{int weight;int value;};int n;int W;int *Weight;int *Value;Weight_Value *p;int point;void function_0_1(){      p=new Weight_Value[1000];      Weight_Value *q=new Weight_Value[1000];      Weight_Value *tempArr=new Weight_Value[1000];      int p_next=1;      int q_next=1;      p[0].weight=0;      p[0].value=0;      for(int i=0;i<n;i++){                  point=0;            for(int j=0;j<=p_next-1;j++){                  tempArr[j].weight=p[j].weight;                  tempArr[j].value=p[j].value;            }            for(int j=0,k=0;j<=q_next-1;){//对q[i]进行处理                  if(p[j].weight+Weight[i]>W){                              q_next--;                              continue;                  }                   q[j].weight=p[j].weight+Weight[i];                   q[j].value=p[j].value+Value[i];                   j++;            }            for(int j=0,k=0;j<=p_next-1||k<=q_next-1;){//求p[i]和q[i]的并集                  if(j<=p_next-1&&tempArr[j].weight<=q[k].weight){                        if(tempArr[j].weight==q[k].weight&&tempArr[j].value<q[k].value){                              p[point].weight=q[k].weight;                              p[point++].value=q[k++].value;                               continue;                        }                        p[point].weight=tempArr[j].weight;                        p[point++].value=tempArr[j++].value;                  }                  else if(k<=q_next-1&&q[k].value>tempArr[j-1].value){                              while(j<=p_next-1&&q[k].value>tempArr[j].value)j++;                        p[point].weight=q[k].weight;                        p[point++].value=q[k++].value;                  }                  else if(k>q_next-1){                                    if(tempArr[j].weight>=q[k-1].weight&&tempArr[j].value>q[k-1].value){                                    p[point].weight=tempArr[j].weight;                                    p[point++].value=tempArr[j++].value;                                    }                                    else j++;                  }                  else k++;            }            p_next=point;            q_next=point;      }}int main(){    //cout<<"请输入容量:"<<endl;    cin>>W;     //cout<<"请输入物品个数:"<<endl;    cin>>n;    Value=new int[n];    Weight=new int[n];    for(int i=0;i<n;i++){      //cout<<"请输入第"<<i+1<<"物品的质量和重量:"<<endl;      cin>>Weight[i]>>Value[i];    }    function_0_1();    cout<<"以下是对p进行输出:"<<endl;    cout<<"point="<<point<<endl;    for(int i=0;i<point;i++)cout<<p[i].weight<<" "<<p[i].value<<endl;    return 0;}
测试如下数据通过:
1000 10088 5385 7059 20100 4194 1264 7179 3775 8718 5138 6447 6311 5056 7312 8396 7554 6023 966 7019 7631 2530 2732 8921 9331 404 4130 893 9312 4621 1660 442 4142 2978 996 8272 4225 1496 6921 7577 2036 2042 5620 237 9246 7119 7024 195 633 1893 1173 6862 3391 6100 8258 6957 783 4832 955 4257 5350 993 1588 7667 6497 3924 4837 8341 2136 7598 4952 7375 857 2857 3123 8655 6393 124 7117 355 2113 1746 7348 1828 724 5170 9485 8848 4648 7755 8093 956 318 8012 3250 4595 566 3092 5125 6380 4316 9结果:2852