***01背包问题***
题意:
有n个重量和价值分别为Wi和Vi的物品。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。
限制条件:
n在[1,100]之间;
wi和vi在[1,100]之间;
W在[1,10000]之间。
动态规划代码如下:
/*动态规划版的01背包问题*/
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=520;
int dp[maxn][20*maxn];
int w[maxn],v[maxn],W,n;
void solve()
{
memset(dp,0,sizeof(dp));
for(int i=0; i<n; i++)
for(int now=0; now<=W; now++)
if(now<w[i])//如果不能装下这个物品
dp[i+1][now]=dp[i][now];
else
dp[i+1][now]=max(dp[i][now],dp[i][now-w[i]]+v[i]);
cout<<dp[n][W]<<endl;
}
int main()
{
while(cin>>n)
{
for(int i=0; i<n; i++)
cin>>w[i]>>v[i];
cin>>W;
solve();
}
return 0;
}
/*
4
2 2
3 3
2 3
4 2
6
6
*/
记忆化搜索代码如下:
/*
01背包问题
根据书上所示的递归调用图可知,对于一个递归函数,
如果参数相同,那么返回的结果必然也应该是相同的,
于是第二次传入相同的参数结果是知道的,但是却还是进行计算浪费了时间
所以应该考虑把把第一次计算时的结果记录下来,以此节约时间。
*/
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=520;
int n,w[maxn],v[maxn],W,dp[maxn][20*maxn];
int fun(int pos,int sum)//pos是当前物品的位置,sun是当前容量。
{
int ans=0;//最大价值。
if(dp[pos][sum]>=0)//如果已经计算过,就直接使用之前的结果。
return dp[pos][sum];
if(pos==n)
ans=0;
else if(w[pos]>sum)//如果装不下该物品。
return fun(pos+1,sum);
else
ans=max(fun(pos+1,sum),fun(pos+1,sum-w[pos])+v[pos]);
dp[pos][sum]=ans;//将结果记录在数组中
}
void solve()
{
memset(dp,-1,sizeof(dp));//初始化。
cout<<fun(0,W)<<endl;
}
int main()
{
while(cin>>n)
{
for(int i=0; i<n; i++)
cin>>w[i]>>v[i];
cin>>W;
solve();
}
return 0;
}
/*
4
2 3
1 2
3 4
2 2
5
7(选择第0,1,3号物品)。
*/
原文地址:http://blog.csdn.net/u014004096/article/details/43795723