Hdu 3496 Watch The Movie (DP_背包)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3496


题目大意:题目给定n部电影,每部电影有时长和量化的意义,要求看m部电影,并且市场控制在l以内,转化为背包问题,让我们在n件物品中找正好m件物品塞进容量为l的包中,求最大的价值。


解题思路:这题写得不好,首先是看错题目了,把正好m件物品看成最多m件物品,Wa了好几次。然后用了三维数组来实现,效率很低,最后才想到滚动数组的写法。现在只说最后的一种方法。

     状态转移方程:if (dp[j-cost[i]][k-1] 可达)  dp[j][k] = max(dp[j][k],dp[j-cost[i]][k-1]+val[i])(dp[j][k]表示容量为j物品正好k件的最大价值)。如果前面没有判断,那么就必须把整个数组初始化为0,那样的话就不能保证物品正好是k,现在判断可达不可达,可以用-1和其他数字表示,-1不可达,其他都可达,这样转移就没有问题。


测试数据:

10
3 2 15
17 16
16 15
15 14

3 2 10
11 100
1 2
9 1

3 2 100
11 100
1 2
9 1
  
3 2 1
11 100
2 2
9 1

10 5 15
1 3
2 4
3 4
4 10
5 4
6 7
7 6
8 9
9 11
10 20


代码:

//二维写法
#include <stdio.h>
#include <string.h>
#define MIN 110
#define MAX 1100
#define max(a,b) (a)>(b)?(a):(b)


int cost[MAX],val[MAX];
int n,m,l,ans,dp[MAX][MIN];


int main()
{
	int i,j,k,t;
	
	
	scanf("%d",&t);
	while (t--) {
		
		scanf("%d%d%d",&n,&m,&l);
		for (i = 1; i <= n; ++i)
			scanf("%d%d",&cost[i],&val[i]);
		
		
		for (i = 0; i <= l; ++i)
			for (j = 0; j <= m; ++j)
				if (j == 0) dp[i][j] = 0;
				else dp[i][j]  = -1;


		for (i = 1; i <= n; ++i)
			for (j = l; j >= cost[i]; --j)
				for (k = m; k >= 1; --k)
					if (dp[j-cost[i]][k-1] != -1)
						dp[j][k] = max(dp[j][k],dp[j-cost[i]][k-1]+val[i]);


		ans = (dp[l][m] == -1 ? 0 : dp[l][m]);
		printf("%d\n",ans);
	}
}
//三维写法
#include <stdio.h>
#include <string.h>
#define MIN 110
#define MAX 1100
#define max(a,b) (a)>(b)?(a):(b)


int cost[MAX],val[MAX];
int n,m,l,ans,dp[MIN][MAX][MIN];


int main()
{
	int i,j,k,t;
	
	
	scanf("%d",&t);
	while (t--) {
		
		scanf("%d%d%d",&n,&m,&l);
		for (i = 1; i <= n; ++i)
			scanf("%d%d",&cost[i],&val[i]);
		
		
		memset(dp,-1,sizeof(dp));
		for (j = 0; j <= l; ++j)
			dp[0][j][0] = 0;
		for (i = 1; i <= n; ++i) {

			for (k = m; k >= 1; --k) 
				for (j = l; j >= cost[i]; --j)
					if (dp[i-1][j-cost[i]][k-1] != -1)
						dp[i][j][k] = max(dp[i][j][k],dp[i-1][j-cost[i]][k-1]+val[i]);


			for (j = 0; j <= l; ++j)
				for (k = 0; k <= m; ++k) {
			
					dp[i][j][k] = max(dp[i][j][k],dp[i-1][j][k]);
					dp[i][j][k] = max(dp[i][j][k],dp[i][j-1][k]);
				}
		}
		for (ans = 0,i = 1; i <= l; ++i)
			ans = max(ans,dp[n][i][m]);
		printf("%d\n",ans);
	}
}

本文ZeroClock原创,但可以转载,因为我们是兄弟。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值