背包问题(贪心法、动态规划法)

1、贪心法

伪代码:

1、v[i]/w[i]赋给结构体数组origData[i].data,将i记录在结构体数组origData[i].index,用来记录原始数组w[i]v[i]下标。

2、按照origData[i].data降序排列,将数组w[]v[]重新排列。

3、将数组x[n]初始化为0  //初始化解向量

4、i=1,   vsum=0;  

5、循环直到(w[i]>C)

5.1x[i]=1;     //将第i个物品放入背包

    5.2C=C-w[i];

5.3vsum+=v[i];

        5.4i++;

输出最优解vsum;

 

源代码:

#include <iostream>

#include <algorithm>

using namespace std;

struct Data

 {

     int data;

     int index;

        bool z;

 };

 Data origData[100];

 

 bool cmp(Data a,Data b){

   return a.data> b.data;

 }

 

float Bag(float w[],float v[],float C,int n){

       int i,x[100],vsum=0;

       float r[100], w1[100], v1[100];

       for(i=1; i<=n; i++)

              r[i]=v[i]/w[i];        

   

 for ( i=1; i<=n; i++){

     origData[i].data = r[i];

     origData[i].index = i;

        origData[i].z=0;

 }

 sort(origData+1,origData+n+1,cmp);  //降序排列

 

 for(i=1; i<=n; i++){

      w1[i]=w[origData[i].index];

      v1[i]=v[origData[i].index];  //改变w[],v[]数组的排列

      //cout<<origData[i].index<<endl;

 }

 cout<<"按照单位重量价值v[i]/w[i]降序排列后的w[]数组为:";

 for(i=1; i<=n; i++){

      cout<<w1[i]<<" ";

 }cout<<endl;

  cout<<"按照单位重量价值v[i]/w[i]降序排列后的v[]数组为:";

  for(i=1; i<=n; i++){

      cout<<v1[i]<<" ";

 }cout<<endl;

 

  memset(x,0 , sizeof(x));   //2、初始化解向量

       i=1;

       while(w1[i]<=C && i<=n){

              origData[origData[i].index].z=1;

              C -= w1[i];

              vsum +=v1[i];

              i++;

       }

    cout<<"选择装进的物品为(1表示装入背包,0表示不装入背包):";

       for(i=1; i<=n; i++) 

              cout<<origData[i].z<<" ";

       cout<<endl;

       return vsum;

}

int main()

{

   int n,i,j,vsum=0;

    float w[100],v[100],C;

    cout<<"输入物品的数量:";

    cin>>n;

    cout<<"输入这"<<n<<"个物品的重量:"<<endl;

    for(i=1; i<=n; i++)

    cin>>w[i];

 

     cout<<"输入这"<<n<<"个物品的价值:"<<endl;

    for(j=1; j<=n; j++)

    cin>>v[j];

 

    cout<<"输入背包容量C"<<endl;

    cin>>C;

   

 

    float rs=Bag(w,v,C,n);

    cout<<"背包中的物品最大价值容量为:"<<rs<<endl;

    

    return 0;

}

 

运行结果:

 

输入物品的数量:3

输入这3个物品的重量:

20 30 10

输入这3个物品的价值:

60 120 50

输入背包容量C

50

按照单位重量价值v[i]/w[i]降序排列后的w[]数组为:10 30 20

按照单位重量价值v[i]/w[i]降序排列后的v[]数组为:50 120 60

选择装进的物品为(1表示装入背包,0表示不装入背包):0 1 1

背包中的物品最大价值容量为:170

Press any key to continue

 

2、动态规划法

 

// Note:Your choice is C++ IDE

#include <iostream>

using namespace std;

int max(int a,int b){

return a>b ? a : b;

}

 

//V[i][j]表示在前i个物品中能够装入容量为j的背包中的物品的价值最大值

//V[i][0] V[0][i]都为0;

 

int KnapSack(int n, int w[ ], int v[ ],int C) {  //n个物品,C为最大容量

    int i,j;

    int V[100][100],x[100];

 

     for (i=0; i<=n; i++)   //初始化第0

 

       V[i][0]=0;

 

     for (j=0; j<=C; j++)   //初始化第0

 

       V[0][j]=0;

 

//主要背包问题实现

 

     for (i=1; i<=n; i++)   //计算第i行,进行第i次迭代

 

       for (j=1; j<=C; j++)

 

          if (j<w[i])   //i个物品不能装入(超重)

 

          V[i][j]=V[i-1][j];

 

         else      //满足装入条件(装入后未超重),但也可不装

 

                     V[i][j]=max(V[i-1][j], V[i-1][j-w[i]]+v[i]);  //装或者不装后的价值的最大值

 

 //求装入背包的物品:1表示装入,0表示未装入

  j=C;  

  for (i=n; i>0; i--){

        if (V[i][j]>V[i-1][j]) {

          x[i]=1;

          j=j-w[i];

              }

       else x[i]=0;

}

 

       //输出装入背包的物品:1表示装入,0表示未装入

  cout<<"输出装入背包的物品:1表示装入,0表示未装入"<<endl;

       for(i=1; i<=n; i++)

              cout<<x[i]<<" ";

              cout<<endl;

 

       return V[n][C];    //返回背包取得的最大价值

 

}

int main(){

 

    int n,i,j,w[100],v[100],C;

    cout<<"输入物品数量:"<<endl;

    cin>>n;

       cout<<"输入这"<<n<<"个物品的重量:"<<endl;

    for(i=1; i<=n; i++)

    cin>>w[i];

 

        cout<<"输入这"<<n<<"个物品的价值:"<<endl;

    for(j=1; j<=n; j++)

    cin>>v[j];

 

       cout<<"输入背包容量C"<<endl;

    cin>>C;

 

    int rs= KnapSack(n,  w,  v,C);

    cout<<"背包中的物品最大价值容量为:"<<rs<<endl;

    return 0;

}

 

输入物品数量:

3

输入这3个物品的重量:

20 30 10

输入这3个物品的价值:

60 120 50

输入背包容量C

50

输出装入背包的物品:1表示装入,0表示未装入

1 1 0

背包中的物品最大价值容量为:180

Press any key to continue

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值