我正在GFG练习门户中做这个0-1背包问题。对于小的输入,代码运行良好。对于更大的输入;超过时间限制";错误我是DP概念的新手,有人能解释一下我的错误是什么吗。我用过(递归+记忆(。
问题链接:https://practice.geeksforgeeks.org/problems/0-1-knapsack-problem0945/1#
这是代码:
int a[10005][10005]; // I have declared this globally.
int knapSack(int W, int wt[], int val[], int n)
{
memset(a,-1,sizeof(a));
if (n == 0 || W == 0)
{
return 0;
}
if(a[n][W]!=-1)
{
return a[n][W];
}
if (wt[n - 1] > W)
{
a[n][W]=knapSack(W, wt, val, n - 1);
return a[n][W];
}
if(wt[n - 1] <= W)
{
a[n][W]= max(val[n - 1]+ knapSack(W - wt[n - 1],wt, val, n - 1),knapSack(W, wt, val, n - 1));
return a[n][W];
}
}
对于较小的输入:
输入:
3//n=输入的数量
4//W行李容量
1 2 3//val[]
4 5 1//wt[]
您的输出是:3
对于较大的输入:
"超过时间限制";
memset(a,-1,sizeof(a));
memset
采用字节中的一个参数,因此您清除了数组的1/4(取决于您的int大小(。幸运的是,值-1变成了字节0xff,当放置在int
的每个字节中时,它再次表示-1。值-1和0在这方面是特殊的。一般来说,最好使用std::fill
。(尽管使用二维阵列会使情况变得复杂(
好的,您有递归调用,如:a[n][W]=knapSack(W, wt, val, n - 1);
大概你一直需要与你已经计算过的相同的。
你需要保留一个数据库,里面有你已经计算过的所有数据。一个简单的方法是制作一个std::map
,键是一个包含四个值的结构,结果就是值。用一个新函数包装实际函数(重命名(,该函数首先检查数据库,如果还不存在,则调用实际函数,将结果存储在数据库中,然后返回。
啊,您似乎已经通过全局数组实现了内存化。。。正如Bob在一条评论中指出的那样,memset
在递归函数中,因此每次调用都会擦除保存的值。