我想在C#中递归地解决背包问题。这是我的代码:
public int f(int n, int remain)
{
if (n < 0) return 0;
if (w[n] > remain)
{
// Thread.VolatileWrite(ref check[n], 0);
check[n] = 0;
return f(n - 1, remain);
}
else
{
int a = f(n - 1, remain);
int b = p[n] + f(n - 1, remain - w[n]);
if (a >= b)
{
// Thread.VolatileWrite(ref check[n], 0);
check[n] = 0;
return a;
}
else
{
// Thread.VolatileWrite(ref check[n], 1);
check[n] = 1;
return b;
}
}
}
w
是一个保存权重的数组,p
是一个保存价格的数组。 n
是项目数,remain
是最大权重。
我的问题在于check
数组。我已经使用这个数组来存储将要放入包中的物品,但它总是不起作用,有时解决方案是正确的,有时候不是。我已经尝试了一切,但无法弄明白。我该如何解决这个问题?
答案 0 :(得分:2)
check数组的用法是错误的,因为它表示最后一个赋值,并且它不必是所选择的赋值。
这是一个反例,解释了为什么它不起作用。
假设:
weights = [1,2]
values = [2,1]
w = 2
现在,让我们来看看会发生什么:
f(1,2):
f(0,2):
f(-1,2) = 0
a = 0
f(-1,1) = 0
b = 2 + 0 = 2
b>a -> check[0] = 1
return f(0,2) = 2
a = 2
f(0,0):
w[0] > 0: check[0] = 0
return f(-1,0) = 0
return f(0,0) = 0
b = 1 + 0 = 1
a > b: check[1] = 0
return f(1,2) = 2
所以,这个问题的最佳解决方案是2(选择第二个元素),但你的解决方案没有选择元素(check = [0,0])
这是因为check
的更改是全局的,而不是调用环境的本地更改,具体而言 - 深层次的分配不依赖于您在更高级别中所做的选择。
要处理它,您可以: