HDU 3496——Watch The Movie

48 篇文章 0 订阅

这道题是一个二维的背包问题,和0-1背包问题极其类似,只不过多了一个维度而已。

第一遍做的时候错误,是因为没有分清楚数组每一维的含义。在这里,dp(i,j,g)的i表示取到第i个物品的时候j表示到达时刻j的时候,g表示取得的物品的数目。最开始把j有时候当做小于等于时刻j的时候,有时候当做正好时刻k的时候,导致了开始的错误。

改正了这个错误以后,提交还是一直不对。发现在ans比较的时候出问题了,ans如果赋初值为-1,那么当无法到达的时候,ans不会变成0.

学长帮我改了一遍代码,我写的时候记录物品的数组(即times跟value)是从0开始赋值的,学长从1开始赋值。从0开始赋值的一个缺点就是在dp中,i等于0的时候要手动赋值。

代码如下(没有进行空间优化):

#include<iostream>
#include<cstring>
using namespace std;

int times[105];
int value[105];
int dp[105][1005][105];

int main(){
	freopen("data.txt","r",stdin);
	ios::sync_with_stdio(false);
	int T;
	cin>>T;
	while(T--){
		int n,m,l;
		cin>>n>>m>>l;
		for(int i=1;i<=n;++i){
			cin>>times[i]>>value[i];
		}
		memset(dp,-1,sizeof(dp));
		/*for(int t=l;t>=0;--t){
			if(t==times[1])
				dp[1][t][1]=value[1];//
		}*/
		for(int i=0;i<=n;++i){
			//for(int t=0;t<=l;++t){
				dp[i][0][0]=0;
			//}
		}
		for(int i=1;i<=n;++i){
			for(int t=0;t<=l;t++)
				for(int g=0;g<=min(i,m);g++)
					dp[i][t][g]=dp[i-1][t][g];
			for(int t=times[i];t<=l;t++){
				//if(t-times[i]<0)break;
				for(int g=0;g<=min(i,m);g++){
					if(g==0||dp[i-1][t-times[i]][g-1]==-1)continue;
					dp[i][t][g]=max(dp[i-1][t-times[i]][g-1]+value[i],dp[i][t][g]);
					//cout<<dp[i][t][g]<<endl;
				}
			}
		}
		int ans=0;
		for(int i=0;i<=l;++i){
			//cout<<dp[n][i][m]<<endl;
			if(dp[n][i][m]>ans)ans=dp[n][i][m];
		}
		cout<<ans<<endl;
	}
	return 0;
}

进行空间优化以后的代码:

#include<iostream>
#include<cstring>
using namespace std;

int times[105];
int value[105];
int dp[1005][105];

int main(){
//	freopen("data.txt","r",stdin);
	ios::sync_with_stdio(false);
	int T;
	cin>>T;
	while(T--){
		int n,m,l;
		cin>>n>>m>>l;
		for(int i=1;i<=n;++i){
			cin>>times[i]>>value[i];
		}
		memset(dp,-1,sizeof(dp));
		/*for(int t=l;t>=0;--t){
			if(t==times[1])
				dp[1][t][1]=value[1];//
		}*/

				dp[0][0]=0;
			//}
		for(int i=1;i<=n;++i){
			for(int t=l;t>=times[i];t--){
				//if(t-times[i]<0)break;
				for(int g=min(i,m);g>=0;g--){
					if(g==0||dp[t-times[i]][g-1]==-1)continue;
					dp[t][g]=max(dp[t-times[i]][g-1]+value[i],dp[t][g]);
					//cout<<dp[i][t][g]<<endl;
				}
			}
		}
		int ans=0;
		for(int i=0;i<=l;++i){
			//cout<<dp[n][i][m]<<endl;
			if(dp[i][m]>ans)ans=dp[i][m];
		}
		cout<<ans<<endl;
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值