现在的位置: 首页 > 综合 > 正文

HDOJ 3496 二维背包

2017年07月15日 ⁄ 综合 ⁄ 共 1121字 ⁄ 字号 评论关闭

题意:有n个物品,每个物品有一个val[i]以及一个时间限制t[i],求再最大时间限制为L时,选择M个物品的最大sumval。

这道题背包的第二维隐藏在只能从n个物品种选择M个这个限制,另一个就是总的时间限制L。

我们可以看成每个物品占用一个可选容量和一个时间限制。可选容量恒为1,而时间限制维t[i]。

状态转移方程dp[k][i][j]=Max(dp[k-1][i-1][j-t[k]]+val[k],dp[k-1][i][j])

有几个陷阱要注意

此题中对第一维的要求是必须选择M个物品,第二维的要求时,只要时间小于L都可以。

因此我们初始化dp,  memset(dp,0x80,sizeof(dp)),是一个非常小的负数。

在背包问题中有如下规定:

如果是要求背包恰好装满的最大值,那么初始化除了dp[0][0]=0,其他都为-inf 
如果没必要把背包装满,而只要求价值最大,那么直接初始化为0就可以了。

解的“连续性”决定了这个规则。

由于第二维不需要装满,因此只要在dp[M][j]中选择最大的那个即可。如果第二维必须装满,则只能选择dp[M][L]


#include<iostream>
#include<cstring>
#define Max(a,b) (a<b?b:a)
#define Min(a,b) (a<b?a:b)
using namespace std;

int c_count;
int N,M,L;  
int t[101];
int val[101];
/*二维背包,设dp[k][i][j]为只使用前k种物品,选择其中i种物品,花费为j时的最大收益。*/
/*物品总个数限制and最大花费限制*/
/*且最后求的是背包第一维恰好满时的最大值*/
/*转移方程 dp[k][i][j]=Max(dp[k][i][j],dp[k-1][i-1][j-t[m]]+val[m])*/
int dp[101][1001];


int main(){
	cin>>c_count;
	while(c_count--){
		cin>>N>>M>>L;
		for(int i=0;i<N;i++){
			cin>>t[i]>>val[i];
		}
		memset(dp,0x80,sizeof(dp));
		dp[0][0]=0;
		for(int i=0;i<N;i++){
			for(int j=M;j>=1;j--){
				for(int k=L;k>=t[i];k--){
					dp[j][k]=Max(dp[j-1][k-t[i]]+val[i],dp[j][k]);
				}
			}
		}
		int ans=0;
		for(int i=L;i>=0;i--){
			if(dp[M][i]>ans){
				ans=dp[M][i];
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

抱歉!评论已关闭.