最简单的就是利用搜索,把每一种情况都考虑。
//深度搜索。复杂度O(2^n)
int dfs(int i,int j)
{
int res;//剩余的空间量。
if(i==n)res=0;//如果i==n则剩余空间量为0。
else if(j<w[i]) res=dfs(i+1,j);//如果物品太大,不装进去。
else res=max(dfs(i+1,j),dfs(i+1,j-w[i])+v[i]);//装和不装的情况都尝试下。
return res;
}
因为在搜索算法中,重复计算的情况较多,我们可以利用数组,把计算结果记录下来,这样就避免了重复计算。
//记忆化搜索。复杂度O(nw).
int dp[n+1][w+1];
memset(dp,-1,sizeof(dp));
int dfs(int i,int j)
{
if(dp[i][j]>=0)return dp[i][j];//如果已经算过这个值,直接返回。
int res;
if(i==n)res=0;
else if(j<w[i])res=dfs(i+1,j);
else res=max(dfs(i+1,j),dfs(i+1,j-w[i])+v[i]);
return d[i][j]=res;//将结果记录在数组中。
}
根据记忆化搜索的算法我们可以得到递推公式:
dp[n][j]=0;
dp[i][j]=dp[i+1][j] (j<w[i])
dp[i][j]=max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]) (其他情况)
//动态规划。复杂度O(nw)
int dp[n+1][w+1];
void solve()
{
for(int i=n-1;i>=0;i--)
for(int j=0;j<=w;j++){
if(j<w[i])dp[i][j]=dp[i+1][j];
else dp[i][j]=max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);
}
printf("%d\n",dp[0][w]);
}