递归代码_01背包_动态规划

递归的思路,代码也写成递归的结构,应更方便理解一些吧。

关于是怎么递归的(也就是那个状态转移方程)大家都写公式,我写文字吧:

所有候选物,要么拿,要么不拿,从后至前挨个考虑。

不拿的话,能获得的价值和只拿前面那些一样,没挤掉前面那些的重量额度,也没增加价值。

如果要拿的话,当前考虑的这个物品自然要占一部分重量,那么可供前面那些物品使用的重量总额就要被挤掉一些。这就要计算一下,在更少的重量额度下,前面那些物品最多能拿多少价值。这就递归了(问题简化了一点,因为待考虑的物品数量少了1个,重量额度也少了一些)。回头再加上当前这个的价值,就是拿当前这个所能获得的总价值。

看看拿和不拿哪个划算。打完收工。

补充1下,当前这个得能拿得下(即使前面一个都不拿)才需要考虑。

补充2下,当问题足够简单后,就用不着继续递归了,比如只需要考虑1个东西和C容量时,显然够容量就拿,不够容量就不拿,犯不着继续绕。

代码如下:

重量,价值
class PackItem
{
public int Weight{get;private set;}
public int Value{get;private set;}
public PackItem(int weight, int value)
{
Weight
= weight;
Value
= value;
}
}

算法代码, 输入背包容量以及一组候选物, 返回最多能装多少价值。(没记录和返回具体选了哪些东西)

算法
class DynamicProgramming
{
public static int ZeroOnePack(int capacity, PackItem[] items)
{
return ZeroOnePackCore(items, items.Length, capacity);
}

private static int ZeroOnePackCore(PackItem[] items, int count, int cap)
{
//不拿就没价值
if (count == 0) { return 0; }

//在cap容量限制下,只在前count-1个中拿,最多多少价值
int noTake = ZeroOnePackCore(items, count - 1, cap);

//当前考虑的这个是否装得下?
if (items[count - 1].Weight <= cap)
{
//以减少前几个的容量配额为代价,拿了当前这个的话有多少总价值
int take = ZeroOnePackCore(items, count - 1, cap - items[count - 1].Weight) + items[count - 1].Value;

//看看减少前面的配额来拿当前这个是否划算
if (noTake < take) { return take; }
}
return noTake;
}
}

拿几个例子测试一下,跟踪跟踪,直观看看吧。

代码
PackItem[] items = {
new PackItem(1,2),
new PackItem(2,3),
new PackItem(3,4),
new PackItem(4,5),
new PackItem(5,6)};
var v
= DynamicProgramming.ZeroOnePack(5, items);

Console.WriteLine(v);
原文地址:https://www.cnblogs.com/robird/p/1935826.html