您好我正在尝试解决经典的背包问题,但到目前为止,我只是设法实现了从我的角度出发并产生正确结果的天真递归:
static int[] objValue;
static int[] objWeight;
static void Main(string[] args)
{
objValue = new int[] { 0, 11, 8, 4, 12, 4, 6, 9, 10 };
objWeight = new int[] { 0, 4, 2, 2, 5, 6, 3, 5, 7 };
int objNumber = objWert.Count() - 1;
int maxWeight = 12;
Console.WriteLine(Knapsack(objNumber, maxWeight));
Console.ReadLine();
}
public static int Knapsack(int i, int w)
{
if (i == 0 || w==0)
{
return 0;
}
if(objWeight[i] > w)
{
return Knapsack(i - 1, w);
}
else
{
int case1 = Knapsack(i - 1, w);
int case2 = objValue[i]+Knapsack(i - 1, w -
objWeight[i]);
return Math.Max(case1,case2);
}
}
到目前为止,这几乎是基本算法本身,即使我有时会对索引感到困惑。它有效....但现在我的动态方法:
static int objNumber;
static int maxWeight;
static int[] objValue;
static int[] objWeight;
static int[,] costTable;
static void Main(string[] args)
{
objValue = new int[] { 0, 10, 5, 7, 12, 8, 6};
objWeight = new int[] { 0, 6, 1, 2, 5, 4, 3};
objNumber = objValue.Count()-1;
maxWeight = 10;
costTable = new int[objNumber+1, maxWeight+1];
for (int i = 0; i <= objNumber; i++)
{
for (int w = 0; w <= maxWeight; w++)
{
if(i==0||w==0)
{ costTable[i, w] = 0; }
else
costTabelle[i, w] = -1;
}
}
int result = Knapsack(objNumber, maxWeight);
Console.WriteLine(result);
Console.ReadLine();
}
public static int Knapsack(int i, int w)
{
if (costTable[i, w] != -1)
{
return costTable[i, w];
}
if (i<=0||w<=0)
{
return 0;
}
if(objWeight[i] > w)
{
costTable[i,w]=Knapsack(i - 1, w);
return costTable[i, w];
}
else
{
int case1 = Knapsack(i - 1, w);
int case2 = objValue[i]+Knapsack(i - 1, w -
objWeight[i]);
costTable[i,w]= Math.Max(case1,case2);
return costTable[i, w];
}
}
正如您所看到的,我只添加了一些代码来保存所有对应的节点/可能性。然而,似乎我在某处犯了一个错误,可能是返回函数或其中一个索引,因为我的costTable看起来像这样:
就我所理解的算法而言,表中不应该有任何-1。我希望你能为我提供一些见解,从12小时开始研究这个问题并找不到错误!
答案 0 :(得分:0)
据我了解,完全没有错。显然在您的实现中,状态表中-1
的初始值表示负无穷大的值(这非常有效,因为输入中的所有值都是非负的,并且递归关系使用值的最大化)。这些值保留在表中,在递归中不检查状态,可能就是这种情况。
话虽如此,您使用的实现不是真的 dynamic programming而是memoization,因为您使用递归实现并通过存储已知状态值来限制其运行时间查找表。但是,技术上很难在概念之间划清界限。