**
动态规划 01背包递归算法 和非递归算法的理解分析 **
**
01完全背包问题描述
题目:一个旅行者有一个最多能放m公斤的背包,现有n件物品,他们的重量分别是w1,w2…,他们的价值分别是c1,c2… ,求旅行者最大能获得的总价值 (每个元素只有一个)
输入
第一行,输入物品的种类数
第二行开始:输入物品的体积 价值
第三行:输入背包的体积
输出 最大总价值
样例输入 输出
这里列举具体的元素来分析一下计算过的过程
dp(n,ww)其中n代表的是物品的个数 ww代表的是背包的体积 dp(n,ww)代表的意思是 在背包容量为ww时从n个物品选出的价值的最大值 接下来举了一个具体的数据来分析一下
这样分析一下就很清楚了 递归有两个需要注意的地方
if(n0||ww0)return 0;//当体积或者可选的物品数目为零时就返回零
else if(v[n]>ww)//当前的元素的体积比背包的体积大的时候这个物品就不选 直接递归到下一个 return dp(n-1,ww);
else //return 选这个物品还是不选这个物品时值最大 返回最大的数值
递归过程就是这么简单
递归代码
在这里插入代码片`#include<stdio.h>
int dpp(int n, int *w, int *v, int ww)
{
if (n == 0 || ww == 0)
return 0;
else if (w[n] > ww)
dpp(n - 1, w, v, ww);
else
{
int A = dpp(n - 1, w, v, ww - w[n]) + v[n];
int B = dpp(n - 1, w, v, ww);
return A > B ? A : B;
}
}
int main()
{
int n,i,w[100],v[100],ww,all;//w表示体积 v表示价值 ww代表的是现在剩下的体积
printf("输入一共有多少种物品 ");
scanf("%d",&n);
for (i = 1; i <= n; i++)
{
printf("输入这种货物的 体积 价值 \n");
scanf("%d%d",&w[i],&v[i]);
}
printf("输入背包的体积 ");
scanf("%d",&ww);
all = dpp(n,w,v,ww);
printf("最大价值是 %d",all);
}
下面用到的数组和上面分析用到的数据是相同的
上面的是递归代码的分析 **其实动态规划就是递归的逆过程 从递归结束的条件出发 断的向后面推 是简单的填表的过程 **
这个表格要怎样填呢,首先填上递归结束的条件 然后按照递归的推导过程不断的填表
用一个二维数组来表示dp[i][j]其中 i 代表的是元素的个数 j 代表的是背包的体积 就是这么简单
非递归代码
在这里插入代码片`#include<stdio.h>
int main()
{
int n, w[20], v[20], dpp[20][40],ww,i,j;//n代表的是总的物品数目 w代表质量 v代表价值 ww 代表背包的体积
printf("输入有多少个元素 ");
scanf("%d",&n);
for (i = 1; i <= n; i++)
{
printf("输入该物品的 体积 价值 \n");
scanf("%d%d",&w[i],&v[i]);
}
printf("输入背包的体积 \n");
scanf("%d", &ww);
//递归结束的条件
for (i = 0; i <= ww; i++)
{
dpp[0][i] = 0;//选择的物体为零个
}
for (i = 0; i <= n; i++)
{
dpp[i][0] = 0;//选择的体积为零
}
//按照有条件来不断的填表
//递归条件理解透彻
for (i = 1; i <= n; i++)
{
for (j = 1; j <= ww; j++)
{
if (w[i] > j)
dpp[i][j] = dpp[i - 1][j];
else
{
int A = dpp[i - 1][j - w[i]] + v[i];
int B = dpp[i - 1][j];
if (A > B)
dpp[i][j] = A;
else
dpp[i][j] = B;
}
}
}
printf("最大的价值是多少 %d",dpp[n][ww]);
return 0;
}