c++动态规划——背包问题
2016-11-08 09:55
281 查看
问题基础:有N件物品和一个容量为C的背包。第i件物品的体积是W[i],价值是V[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
![](https://img-blog.csdn.net/20161108095819672?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
怎样才能得到放入书包物品的的最大价值呢?
解决方法——【动态规划】
运筹学的分支,纠结决策过程最优化的数学方法
把多阶段问题分解为相互联系单一阶段小问题求解,上一阶段的决策可以对下一阶段的决策产生影响
各个阶段的决策选择最优,从而使整个过程达到最优
令Vi、Wi 分别表示第i个物品的价值和体积,V(i,j)表示前i个物品能装入背包容量为j的背包的最大价值,有以下动态规划函数:
![](https://img-blog.csdn.net/20161108100012315?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
算法大概:即填写二维矩阵,行数为物品个数加1,列数为背包承重加1
例如,有5个物品,其重量分别是{2, 2, 6, 5, 4},价值分别为{6, 3, 5, 4, 6},背包的容量为10,求装入背包的物品和获得的最大价值。
第一阶段,只装入前1个物品,要求能够得到最大价值;
第二阶段,只装入前2个物品,要求能够得到最大价值;这个问题求解要在第一阶段最优解的基础上进行;
依此类推,直到第n个阶段。
最后,V(n,C)便是在容量为C的背包中装入n个物品时取得的最大价值。
每个阶段问题的求解都是基于前一个阶段的解是最优的基础上。
![](https://img-blog.csdn.net/20161108100305302?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
每次增加一个物品放入背包,如果可以放入,设该物品重量为w1,价值v1,得到其放入之后背包的总重量W,减去这个物品的重量w1,那么W-w1这个重量的列的最大价值加上v1如果大于该位置(该行该列)上一行的价值的值,就更新此处的value值,表明这个物品放入背包,不然就继承上一行的value值。
直接上代码:
怎样才能得到放入书包物品的的最大价值呢?
解决方法——【动态规划】
运筹学的分支,纠结决策过程最优化的数学方法
把多阶段问题分解为相互联系单一阶段小问题求解,上一阶段的决策可以对下一阶段的决策产生影响
各个阶段的决策选择最优,从而使整个过程达到最优
令Vi、Wi 分别表示第i个物品的价值和体积,V(i,j)表示前i个物品能装入背包容量为j的背包的最大价值,有以下动态规划函数:
算法大概:即填写二维矩阵,行数为物品个数加1,列数为背包承重加1
例如,有5个物品,其重量分别是{2, 2, 6, 5, 4},价值分别为{6, 3, 5, 4, 6},背包的容量为10,求装入背包的物品和获得的最大价值。
第一阶段,只装入前1个物品,要求能够得到最大价值;
第二阶段,只装入前2个物品,要求能够得到最大价值;这个问题求解要在第一阶段最优解的基础上进行;
依此类推,直到第n个阶段。
最后,V(n,C)便是在容量为C的背包中装入n个物品时取得的最大价值。
每个阶段问题的求解都是基于前一个阶段的解是最优的基础上。
每次增加一个物品放入背包,如果可以放入,设该物品重量为w1,价值v1,得到其放入之后背包的总重量W,减去这个物品的重量w1,那么W-w1这个重量的列的最大价值加上v1如果大于该位置(该行该列)上一行的价值的值,就更新此处的value值,表明这个物品放入背包,不然就继承上一行的value值。
直接上代码:
#include<stdio.h> #include<stdlib.h> #include<iostream> #include<queue> #include<climits> #include<cstring> #include<stdlib.h> #include <time.h> #include<ctime> #include <iomanip> using namespace std; void Add(int *m[],int weight[],int value[],int num,int content)//n代表物品的个数 { int i,j; for(j=0;j<=content;j++)//采用从底到顶的顺序来设置m[i][j]的值,首先放weight[num] { if(j<weight[num])//j小于weight[num],所对应的值设为0 { m[num][j] = 0; } else//否则就为可以放置 { m[num][j]=value[num]; } } for(i=num-1;i>=1;i--)//对剩下的num-1个物品进行放置 { for(int j=0;j<=content;j++) { if(j<weight[i])//如果j<weight[i]则当前位置就不能放置,它等于上一个位置的值。 { m[i][j]=m[i+1][j]; } else//否则,就比较到底是放置之后的值大,还是不放置的值大,选择其中较大者。 { m[i][j]=m[i+1][j]>m[i+1][j-weight[i]]+value[i]?m[i+1][j]:m[i+1][j-weight[i]]+value[i]; } } } } void putout(int *m[],int num,int content,int x[],int weight[]) { int j=content,i; for(i=1;i<=num-1;i++) { if(m[i][j] == m[i+1][j]) { x[i]=0;//0表示不放进背包该物品 } else { x[i]=1;//放进背包该物品 j=j-weight[i]; } } x[num]=m[i][j]?1:0; } int main() { while(true){ int times=100000,t;//运行总次数 double alltime=0; int num,content; //物品的个数和背包容量 cout<<"输入物品个数:"; cin>>num; cout<<"输入背包容量:"; cin>>content; int *weight=new int[num+1];//物品的重量,其中0号位置不使用 。 int *value=new int[num+1];//物品对应的待加,0号位置置为空。 int i,j; for(t=0;t<times;t++) { clock_t start,finish; srand((int)time(NULL));//srand()函数产生一个以当前时间开始的随机种子.应该放在for等循环语句前面 不然要很长时间等待 for(i=1;i<=num;i++) { //weight[i]=rand()%(content/2);//生成0~content/2的整数 //value[i]=rand()%(content/2); weight[i]=1 + content * rand() / (RAND_MAX + 1);//生成1~content的随机数 value[i]=1 + content * rand() / (RAND_MAX + 1); } weight[0]=0; value[0]=0; /*cout<<setw(5)<<"编号"<<setw(5)<<"重量"<<setw(5)<<"价值"<<endl; for(i=1;i<=num;i++) { cout<<setw(3)<<i<<setw(5)<<weight[i]<<setw(5)<<value[i]<<endl; } cout<<endl;*/ int *x=new int[num+1]; int **m = new int*[num+1]; for(i=0;i<num+1;i++) { m[i]=new int[content+1]; } for(i=0;i<num+1;i++) { for(j=0;j<content+1;j++) { m[i][j]=0; } } start=clock();//开始时间 Add(m,weight,value,num,content); putout(m,num,content,x,weight); finish=clock();//结束时间 alltime=alltime+(double)(finish-start);//times次计算的时间总和 /*for(i=0;i<=num;i++) { for(j=0;j<=content;j++) { printf("%2d ",m[i][j]); } cout<<endl; } cout<<"放入背包的物品编号:\n"; for(i=1;i<=num;i++) { if(x[i]==1) { cout<<i<<" "; } } cout<<endl;*/ } cout<<times<<"组数据平均运行时间:"<<alltime/times<<"ms"<<endl;//times次运行的平均时间,结果更精确 cout<<"-----------------------------------"<<endl; } return 0; }代码中还包括运行时间的计算,随机数的生成。
相关文章推荐
- 0-1背包问题与完全背包问题C++实现 动态规划
- 0-1背包问题与完全背包问题C++实现 动态规划
- 0-1背包问题与完全背包问题C++实现 动态规划
- c++实现0-1背包问题完整源码(动态规划实现)
- 0/1背包问题 - 动态规划(C++实现)
- 背包问题,动态规划求解,matlab代码,c++代码
- c++实现0-1背包问题完整源码(动态规划实现)
- 0-1背包问题,poj 3624 Charm Bracelet动态规划-解题报告,增加最优路径构建
- 动态规划 ------0-1背包问题
- 用动态规划求解0-1背包问题
- 0/1背包问题(动态规划求解)
- 【笔记】【算法学习】【动态规划】背包问题总结(1)
- 动态规划解决0-1背包问题
- 用贪心算法求解普通背包问题的C++代码
- 0-1背包问题--动态规划解法
- [动态规划]背包问题(找零/子集和/编辑距离)
- POJ 3624 0-1背包问题 动态规划
- 贪心算法运用于背包问题(C++实现)
- POJ 3624 0-1背包问题 动态规划
- 0-1背包问题(C++)