您的位置:首页 > 其它

01背包问题

2014-10-31 21:38 169 查看
01背包
01背包是最简单的动归问题,下面主要以代码的形式介绍一下经典的二维01,空间优化后的一维01,和简单的小优化。

二维01背包:

<span style="font-size:14px;">#include<iostream>
using namespace std;
struct Arr
{
int w,v;
}arr[1000];
int dp[1000][1000];
int Max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int n,m;
while(cin>>n>>m)
{
for(int i=1;i<=n;i++)
{
cin>>arr[i].w>>arr[i].v;
for(int j=0;j<=m;j++)
{
dp[i][j]=0;
}
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
if(j<arr[i].w)
{
dp[i][j]=dp[i-1][j];
}
else
{
dp[i][j]=Max(dp[i-1][j],dp[i-1][j-arr[i].w]+arr[i].v);
}
}
}
cout<<dp
[m]<<endl;
}
return 0;
}</span>
给上述代码一组测试数据:

n=3,m=5;

1 3

2 3

3 3



空间优化为1维:

<span style="font-size:18px;"><span style="font-size:14px;">#include<iostream>
using namespace std;
struct Arr
{
int w,v;
}arr[1000];
int dp[1000];
int Max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int n,m;
while(cin>>n>>m)
{
for(int i=0;i<=m;i++)
dp[i]=0;
for(int i=1;i<=n;i++)
cin>>arr[i].w>>arr[i].v;
for(int i=1;i<=n;i++)
{
for(int j=m;j>=<span style="font-family: Arial, Helvetica, sans-serif;">arr[i].w</span><span style="font-family: Arial, Helvetica, sans-serif;">;j++)//与二维比  这里选择逆序,因为这样能保证求dp[i]时,可以利用dp[i-1],不明白看下图</span>
{
dp[j]=Max(dp[j],dp[j-arr[i].w]+arr[i].v);
}
}
cout<<dp[m]<<endl;
}
return 0;
}</span></span>
测试数据同上:

对照着图看状态转移方程,很容易理解。



1维代码中,还有一个小优化,就是for(int j=arr[i].w;j<=m;j++)这句,其实j没必要每次从0开始,比arr[i].w根本不用考虑,当m非常大时,效果明显。

完全背包
完全背包代码不在贴了,只是把01背包代码中dp[i][j]=Max(dp[i-1][j],dp[i-1][j-arr[i].w]+arr[i].v);改为dp[i][j]=Max(dp[i-1][j],dp[i][j-arr[i].w]+arr[i].v)即可。看不懂的话,像上面那样,自己画出过程图,就比较好理解了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: