01背包问题:
有n个重量和价值分别为wi,vi的物品。从这些物品中挑出总重量不超过W的物品,求所有挑选方案中价值总和的最大值
记忆化搜索与动态规划:
先来看看单纯的递归是怎么写的
int func1(int i,int n,int lastWight)
{
if(i==n) return 0;
if(lastWight<W[i])
reutrn func(i+1,n,lastWight);//放不下第i个物品
else
return max(func(i+1,n,lastWight),func(i+1,n,lastWight-W[i])+V[i]);
//可要可不要时,取出两个中的最大值。
}
我们可以知道,在递归调用的过程中有的函数式被重复调用,而它的返回的结果是一样的。所以可以用数组来进行记忆。
int dp[MAX][MAX];
int func2(int i,int n,int lastWight)
{
if(dp[i][lastWight]!=-1) return dp[i][lastWight];
//如果这个函数之前已经被调用过了,就可以直接返回。
int res;
if(i==n)
{
res=0;
}
else if(lastWight<W[i])
{
res=func(i+1,n,lastWight);
}
else
res=max(func(i+1,n,lastWight),func(i+1,n,lastWight-W[i])+V[i]);
dp[i][lastWight]=res;//记下来。
return res;
}
我们把要求结果范围内的所有情况都求出来直接用数组进行推导
动态规划:
int func3()
{
int i,j;
for(j=0;j<W;j++)
dp[0][j]=0;
for(i=0;i<n;i++)
{
for(j=0;j<=W;j++) //w是背包能盛物品最大的重量。
{
if(j<W[i]) dp[i+1][j]=dp[i][j];//表示不能盛下。
else dp[i+1][j]=max(dp[i][j],dp[i][j-W[i]]+V[i]); //表示把第i个物品选了。
}
}
return dp[n][W];
}