UVA 12563:jin ge jin qu hao

题目网址:

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34887

分析:题目的大概意思就是在剩余时间内,在给定了歌的时间的n首歌里,在所唱歌数最多的情况下,最后剩余的时间最少。这题的考点是比较明显的01背包,但是不容易想到的是我们不需要对歌的时间进行DP,只需要最后求出剩余时间最小就 可以了,所以我们可以对歌数进行DP,并储存所选歌曲的总时间,最后扫一遍就可以了

代码:

#include<cstdio>
#include<cstring>
int dp[9680], songtime[60];//由于剩余时间一定小于所有歌曲加上劲歌金曲的总时间,所以数组只要比50*180+678大一点即可
int max(int a, int b)
{
	return a > b ? a : b;
}
int main()
{
	int totaltime, i, j, n, t, T,ans;
	scanf("%d", &T);
	for (t = 1;t <= T;t++)
	{
		scanf("%d%d", &n,&totaltime);
		for (i = 0;i < n;i++)
			scanf("%d", &songtime[i]);
		memset(dp, -1, sizeof dp);
		dp[0] = 0;
		//-1与0的意义为dp数组中当前阶段歌曲时间或当前阶段所选歌曲总时间会被标记,最终一定比不满足条件的数组位置的对应数大,达到了储存所选歌曲总时间的目的
		for (i = 0;i < n;i++)
			for (j = totaltime;j >= songtime[i];j--)
				dp[j] = max(dp[j], dp[j - songtime[i]] + 1);
		for (j = ans = totaltime - 1;j >= 0;j--)//由于一定得剩余时间给劲歌金曲,所以不能取刚好等于初始剩余时间的歌曲总数
			if (dp[ans] < dp[j])
				ans = j;//从后往前扫,保证在歌曲数最大的情况下,首先取到歌曲总时间较大的情况,所以只是<而没有=
		printf("Case %d: %d %d\n", t,dp[ans]+1, ans + 678);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值