01背包问题
2014-10-31 21:38
169 查看
01背包
01背包是最简单的动归问题,下面主要以代码的形式介绍一下经典的二维01,空间优化后的一维01,和简单的小优化。
二维01背包:
n=3,m=5;
1 3
2 3
3 3
![](http://img.blog.csdn.net/20141101092104455?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDA3Njc2OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
空间优化为1维:
对照着图看状态转移方程,很容易理解。
![](http://img.blog.csdn.net/20141101092919616?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDA3Njc2OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
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)即可。看不懂的话,像上面那样,自己画出过程图,就比较好理解了。
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)即可。看不懂的话,像上面那样,自己画出过程图,就比较好理解了。