您的位置:首页 > 其它

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

2012-07-27 09:04 155 查看
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

选取数据测试

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息