动态规划实验 0-1背包问题 代码+流程图
1.实验内容 0-1背包问题:若有物品n个,每个物品的价值Value,用vi表示,每个物品的重量weight用wi表示,其中vi和wi均为非负数。设背包的总容量为W,且W为非负数。现需要考虑的问题是:如何选择装入背包的物品,使装入背包的物品总价值最大。
【动态规划解步骤】 第一步,刻画问题的最优解子结构。可以将背包问题的求解过程看作是进行一系列的决策过程,即决定哪些物品应该放入背包,哪些物品不放入背包。如果一个问题的最优解包含了物品n,即xn=1,那么其余x1,x2,…,x(n-1)一定构成子问题1,2,…,n-1在容量W-wn时的最优解。如果这个最优解不包含物品n,即xn=0,那么其余x1,x2,…,x(n-1)一定构成子问题1,2,…,n-1在容量W时的最优解。
第二步,递归定义最优解的值,根据上述分析的最优解的结构递归地定义问题最优解。设G[i,w]表示背包容量为w时,i个物品导致的最优解的总价值,得到下式。显然要求G[n,w]:
2.算法流程图及说明
3.核心代码解释
/*
c[i][w]表示背包容量为w时,i个物品导致的最优解的总价值,大小为(n+1)*(w+1)
v[i]表示第i个物品的价值,大小为n
w[i]表示第i个物品的重量,大小为n
*/
#include <iostream>
using namespace std;
void Dny(int n, int W, int c[][18], int* v, int* wei)//构建最优解子结构
{
memset(*c, 0, (W + 1) * sizeof(int));
for (int i = 1; i <= n; i++)//构建最优子结构从装入一个物品开始
{
c[i][0] = 0;
for (int w = 1; w <= W; w++)
{
if (wei[i - 1] > w) //此处比较是关键,当当前第一个物品重量大于当前背包容量时,最优子结构等于上一所装数量的最优解
{
c[i][w] = c[i - 1][w];
}
else//否则可以装入
{
int temp = c[i - 1][w - wei[i - 1]] + v[i - 1]; //注意wei和v数组中的第i个应该为wei[i-1]和v[i-1]
if (c[i - 1][w] > temp)//如果上一个最优子结构大于当前价值,则不装,否则装入。
{
c[i][w] = c[i - 1][w];
}
else
c[i][w] = temp;//写入当前最优解
}
}
}
}
void assign(int c[][18], int* x, int* wei, int n, int W)
{
int w = W;
for (int i = n; i >= 2; i--)
{
if (c[i][w] == c[i - 1][w])
{
x[i - 1] = 0;
}
else
{
x[i - 1] = 1;
w = w - wei[i - 1];
}
}
if (c[1][w] == 0)
x[0] = 0;
else
x[0] = 1;
}
int main()
{
int n = 5;
int W = 17;
int w[] = {
3, 4, 7, 8, 9 };
int v[] = {
4, 5, 10, 11, 13 };
int c[6][18] = {
0 };
Dny(n, W, c, v, w);
cout << c[5][17] << endl;
int x[5];
assign(c, x, w, n, W);
cout << "Here is the assignment!" << endl;
for (int i = 0; i < n; i++)
cout << x[i] << endl;
for (i = 0; i <= n; i++)
{
for (int j = 0; j <=W; j++)
cout << c[i][j] << " ";
cout << endl;
}
return 0;
}
if (wei[i - 1] > w) c[i][w] = c[i - 1][w]; else int temp = c[i - 1][w - wei[i - 1]] + v[i - 1];
然后构建表格!当运行到装下一个物品的时候,判断上一个物品是放着还是取出!
上一篇:
通过多线程提高代码的执行效率例子
