动态规划 - 01背包问题
1.使用递归遍历(穷举)求解:
01背包问题:给定 n 种物品和一个重量(容量)(限定条件)为 w 的背包,物品 i 的重量是 wi,其价值为 vi。(每种物品只有一个)问:如何选择装入背包的物品,使得装入背包中的物品的价值最大。
//VC6.0--------------------------
#include"stdafx.h"
#include <cmath>
#include <iostream>
using namespace std;
//----------全局变量------------
#define n 4 //number //物品数量
#define max_w 9 //weight //可承受重量(最大重量)
int value[n]={2,3,4,5}; //物品价值
int weight[n]={3,4,5,6}; //物品重量
//最大价值 以及解向量
int max_v=0; int x[n]={0};
int nx[n]={0}; //当前解的情况
//-----------------------递归-----------------------
void beibao01(int i,int v,int w) //第i个物品 总价值 总重量
{
//物品已遍历完毕
if(i>n-1) return;
//将第i个物品放入 改变解向量
if((w+weight[i]) <= max_w)
{
nx[i]=1;
//如果大于之前的解的最大价值 则更新最大价值以及解向量
if((v+value[i]) > max_v)
{
max_v = v+value[i];
for(int k=0;k<n;k++) x[k]=nx[k];
}
beibao01(i+1,v+value[i],w+weight[i]);
}
//不放第i个物品 刷新解向量
for(int k=i;k<n;k++) nx[k]=0;
beibao01(i+1,v,w);
}
//------------------------------------------------------
void main()
{
beibao01(0,0,0);
//输出答案
cout<<max_v<<endl;
for(int k=0;k<n;k++) cout<<x[k]<<" ";
}
max_w=8:
2. 动态规划算法求解
//VC6.0--------------------------
#include "stdafx.h"
#include <cmath>
#include <iostream>
using namespace std;
int max(int a,int b){
if(a>b) return a;
else return b;
}
void solution(int i,int j);
//----------全局变量------------
#define n 4 //number //物品数量
#define max_w 9 //weight //可承受重量(最大重量)
int value[n]={2,3,4,5}; //物品价值
int weight[n]={3,4,5,6}; //物品重量
int max_v=0; int x[n]={0}; //最大价值 以及解向量
int real_w=0; //包含最大价值背包的实际重量
//动态规划表 dynamic programming table
int dpt[n][max_w+1]={0}; // dpt[i][j]=k 表示前i个物品重量为j的最大价值为k
//-----------------------状态转移方程-----------------------
//不考虑单个物品重量超过max_w 不考虑单个物品价值为0 等特殊情况
void beibao01() //解出动态规划表以及 最大价值 背包实际重量 解向量
{
int i,j;
//先填写第一行表
for (j = 0; j <= max_w; j++)
if(j >= weight[0])
dpt[0][j] = value[0];
else
continue;
//由递推式 填完表
for (i = 1; i < n; i++) {
for (j = 1; j <= max_w; j++) {
//容量为j的背包装不下 第i个物品
if (j < weight[i])
dpt[i][j] = dpt[i-1][j];
//能装下 装完第i个物品之后背包重量为j 则其价值为 dpt[i-1][现在重量-第i物品重量] + 第i物品价值
else{
//取其最大值 即为最优子策略
dpt[i][j] = max(dpt[i-1][j], dpt[i-1][j-weight[i]] + value[i]);
if(dpt[i][j] > max_v){
max_v = dpt[i][j];
real_w = j;
}
}
}
}
//求一个最优解
solution(n-1,real_w);
}
//----------求解向量-------------
void solution(int i,int j)
{
//第一个物品是否放入背包?
if(i == 0){
//没有放入
if(j == 0) x[i] = 0;
else x[i] = 1;
}
else{
//第i个物品没有放入包内 寻找上一个最优子策略
if(dpt[i][j] == dpt[i-1][j]){
x[i] = 0;
solution(i-1,j);
}
//第i个物品放入了包内 寻找上一个最优子策略
else{
x[i] = 1;
solution(i-1,j-weight[i]);
}
}
}
//------------------------------------------------------
void main()
{
int i,j;
beibao01();
//输出答案
cout<<"物品价值:"<<endl;
for (i = 0; i < n; i++)
cout<<value[i]<<" ";
cout<<endl;
cout<<"物品重量:"<<endl;
for (i = 0; i < n; i++)
cout<<weight[i]<<" ";
cout<<endl;
cout<<"动态规划表:"<<endl;
for (i = 0; i < n; i++) {
for (j = 0; j <= max_w; j++) {
cout << dpt[i][j] << ' ';
}
cout << endl;
}
cout<<"实际重量:"<<real_w<<endl;
cout<<"最大价值:"<<max_v<<endl;
cout<<"解向量:";
for(int k=0;k<n;k++) cout<<x[k]<<" ";
cout<<endl;
}
max_w=8:
max_w=9:
3.对2进行简化
//VC6.0--------------------------
#include "stdafx.h"
#include <cmath>
#include <iostream>
using namespace std;
//----------全局变量(输入信息)------------
#define n 4 //数量
#define max_w 8 //最大重量
int value[n]={2,3,4,5}; //价值
int weight[n]={3,4,5,6}; //重量
//----------最大值函数--------
int max(int a,int b){
if(a>b) return a;
else return b;
}
//-----------------------填写动态规划表-----------------------
int beibao01(int *x)
{
int i,j;
int dpt[n][max_w+1]={0}; //动态规划表
int max_v; //最大价值
int real_w; //实际重量
//--------------第一行------------
for (j = 0; j <= max_w; j++)
if(j >= weight[0])
dpt[0][j] = value[0];
//--------------其余行------------
for (i = 1; i < n; i++)
{
for (j = 1; j <= max_w; j++)
{
if (j < weight[i])
dpt[i][j] = dpt[i-1][j];
else
{
dpt[i][j] = max(dpt[i-1][j], dpt[i-1][j-weight[i]] + value[i]);
}
}
}
//求最大价值 以及实际重量
for (j = 1; j <= max_w; j++)
{
if(dpt[n-1][j] > max_v)
{
max_v = dpt[n-1][j];
real_w = j;
}
}
//求一个最优解
for (i = n-1; i > 0; i--)
{
if(dpt[i][real_w ] != dpt[i-1][real_w ])
{
x[i] = 1;
real_w = real_w-weight[i];
}
}
if(real_w != 0)
x[0] = 1;
//返回最大值
return max_v;
}
//------------------------------------------------------
void main()
{
//解向量
int x[n]={0};
//输出答案
cout<<"最大价值:"<<beibao01(x)<<endl;
cout<<"解向量:";
for(int k=0;k<n;k++)
cout<<x[k]<<" ";
cout<<endl;
}
max_w=8:
参考博文:https://blog.csdn.net/qq_38410730/article/details/81667885
来源:CSDN
作者:das白
链接:https://blog.csdn.net/qq_38204686/article/details/103899845