首页 > 其他分享 >01背包问题动态规划法求解

01背包问题动态规划法求解

时间:2022-12-01 18:05:44浏览次数:42  
标签:01 sequence int 规划法 value 商品 背包 it1


01背包问题动态规划法求解


一问题描述:

有N件商品,每种商品都有各自的重量和价值,有一个背包,总容量是V。现在从这N种商品中挑选若干件放入背包中,要求每种商品最多放入一次,要使放入背包中商品总价值最大且商品总重量不超过背包容量,如何选择商品?

二解题思路

考虑将第i件商品放入背包之间背包的状态,此时,背包里有i-1件商品,最大的价值是f[v]。那么背包的最大价值应该是max{f[v],f[v-w[i]+c[i]}。

v是此时背包的容量,v可变,从0到V。w[i]是第i件商品的重量,c[i]是第i件商品的价值。也就是说当要将第i件商品放入背包之间背包的最大价值取决于背包之前的状态和第i件商品本身。

三动态规划法求解

#include<iostream>

#include<vector>

#include<set>

#include<cstdlib>

using namespacestd;

 

class Commodity //商品类

{

private:

      int sequence; //商品序号

      int weight; //商品重量

      int cost; //商品价值

public:

      static const int N; //商品总数

      Commodity(int s=0,int w=0,int c=0)

      {

           sequence=s;

           weight=w;

           cost=c;

      }

      Commodity(const Commodity& c)

      {

           sequence=c.sequence;

           weight=c.weight;

           cost=c.cost;

      }

      const Commodity& operator=(constCommodity& c)

      {

           sequence=c.sequence;

           weight=c.weight;

           cost=c.cost;

           return *this;

      }

      inline int getSequence() const

      {

           return sequence;

      }

      inline int getWeight() const

      {

           return weight;

      }

      inline int getCost() const

      {

           return cost;

      }

      inline void setSequence(int s=0)

      {

           sequence=s;

      }

      inline void setWeight(int w=0)

      {

           weight=w;

      }

      inline void setCost(int c=0)

      {

           cost=c;

      }

};

 

const intCommodity::N=6;

 

class Bag

{

private:

      int Volume; //背包总容量

      vector<Commodity>CommoditySet; //商品集合

      typedef struct Tag //关键算法所涉及的结构体

      {

           int v; //v=Volume...0

           int value;  //value是与v对应的装入背包中商品最大价值,如v=10,value=8表示此时背包容量是10,装入其中商品最大价值是8

           set<int>sequence; //当达到最大价值v时,装入背包的商品编号

      };

      vector<Tag>tag;

      bool AddToBag(int v,int sequence) //判断编号为sequence的商品是否能够加入背包中

                                         //v表示背包的容量v=Volume...

      {

           if(v>=CommoditySet[sequence].getWeight())return true;

           else return false;

      }

      bool AlterBagValue(intv,vector<Tag>::reverse_iterator it,int sequence) //修改背包的最大价值,前提是AddToBag函数返回真

      {

           intreminder=v-CommoditySet[sequence].getWeight(); //没有放入第i件商品前背包的重量

           if(it->value<tag[reminder].value+CommoditySet[sequence].getCost())//此时应该放入第i件商品到背包中

           {

                 it->value=tag[reminder].value+CommoditySet[sequence].getCost();

                 return true; //背包被修改,函数返回true

           }

           else return false; //背包没有被修改,函数返回false

      }

      void AddCommodityToBag(intv,vector<Tag>::reverse_iterator it,int sequence) //向背包中增加商品

      {

           intreminder=v-CommoditySet[sequence].getWeight();

           set<int>::iterator it1;

           it->sequence.clear(); //很重要,必须把当前的商品编号清空

           for(it1=tag[reminder].sequence.begin();it1!=tag[reminder].sequence.end();it1++)

           {

                 it->sequence.insert(*it1);

           }

           it->sequence.insert(sequence);

      }

      void ShowCommodity(int sequence) //显示编号是sequence的商品信息

      {

           ints=CommoditySet[sequence].getSequence();

           intw=CommoditySet[sequence].getWeight();

           intc=CommoditySet[sequence].getCost();

           cout<<"背包里商品信息: ";

           cout<<"编号:"<<s<<" ";

           cout<<"重量:"<<w<<" ";

           cout<<"价值:"<<c<<endl;

      }

public:

      Bag(int V):Volume(V)

      {

           int i;

           int w,c;

           for(i=0;i<Commodity::N;i++)

           {

                 cout<<"请输入第"<<i<<"件商品的重量:";

                 cin>>w;

                 if(!cin.good()) exit(1);

                 cout<<"请输入第"<<i<<"件商品的价值:";

                 cin>>c;

                 if(!cin.good()) exit(1);

                 Commodity commodity(i,w,c);

                 CommoditySet.push_back(commodity);

           }

           for(i=0;i<=Volume;i++)

           {

                 Tag t;

                 t.v=i;

                 t.value=0;

                 t.sequence.clear();

                 tag.push_back(t);

           }

      }

      void Solution() //用动态规划法解决背包问题

      {

           int i;

           int v;

           vector<Tag>::reverse_iteratorit; //反向迭代器

           for(i=0;i<Commodity::N;i++)

           {

                 for(v=Volume,it=tag.rbegin();AddToBag(v,i)&& it!=tag.rend();it++,v--)

                 {

                      //当背包确实被修改时,才应该增加商品

                      if(AlterBagValue(v,it,i))  AddCommodityToBag(v,it,i);                         

                 }

           }

      }

      void showResult()

      {

           vector<Tag>::reverse_iteratorit;

           set<int>::const_iterator it1;

           int v,value;

           for(it=tag.rbegin();it!=tag.rend();it++)

           {

                 v=it->v;

                 value=it->value;

                 cout<<"当背包重量是"<<v<<"时背包里商品最大价值是"<<value<<endl;

                 for(it1=it->sequence.begin();it1!=it->sequence.end();it1++)

                 {

                      ShowCommodity(*it1);

                 }

           }

      }

};

 

void main()

{

      Bag bag(40);

      bag.Solution();

      bag.showResult();

}

四测试

 背包容量是40,选取数据测试

当背包容量是30

选取数据测试

标签:01,sequence,int,规划法,value,商品,背包,it1
From: https://blog.51cto.com/u_15899033/5903532

相关文章