Jin Ge Jin Qu UVa12563

题意:

       KTV里面有n首歌曲你可以选择,每首歌曲的时长都给出了. 对于每首歌曲,你最多只能唱1遍. 现在给你一个时间限制t (t<=10^9) , 问你在最多t-1秒的时间内可以唱多少首歌曲num , 且最长唱歌时间是多少time (time必须<=t-1) ? 最终输出num+1 和 time+678 即可.

       注意: 你需要优先让歌曲数目最大的情况下,再去选择总时长最长的.

分析:

       其实本题本质上就是一个标准的01背包问题. 问你<=t-1时间内最多可以选择哪些歌曲使得 (数据1,数据2)最优. 这里的数据1是歌曲数目,数据2是歌曲总时长, 且数据1优先.

       一般我们做的01背包问题都是问你<=t-1的时间内, 最多选择哪些歌曲使得歌曲数目最多 总时间最长. 但是本题需要同时考虑两个最优条件, 那么该怎么做呢?

       我们令dp[i][j]==x 表示当决策完全前i个物品后(选或不选), 所选的总歌曲时长<=j时, 所得到的最优状态为x. (这里的x就不是平时我们所说的最长时间或最多歌曲数目了)

       怎么理解最优状态为x这个事实呢? 假设有两种选择前i个歌曲的方法能使得决策完前i个物品且总时长<=j时的状态分别为x1 和x2.

       那么如果x1状态的歌曲数目> x2状态的歌曲数目, 那么明显x1状态更优. 所以dp[i][j]应==x1.

       如果x1状态的歌曲数目与x2的相等, 但是x2状态的时长 > x1状态时长, 那么此时x2状态更优. 所以dp[i][j]应==x2.

       经过上面的分析,我们可以用一个(具有歌曲数和总时长双属性的)结构体来表示一个状态. 且可以得到下面状态转移公式:

       dp[i][j] =最优( dp[i-1][j],  在dp[i-1][j-t[i]]的基础上选择第i首歌后得到的新状态tmp)

       所有dp初始化为0即可. 最终我们所求为dp[n][max_time]

 

       最后还有一个问题就是t<=10^9.我们不可能循环判断j到10^9. 其实一共50首歌曲, 每首歌曲最多180秒, 所以我们求出所有歌曲的时长和sum(sum<=50*180==9000).

       如果t-1>=sum, 那么明显所有歌曲都能被选一遍.

       如果t-1<sum,那么明显我们需要遍历到dp[i][t-1]为止.

       程序实现用的滚动数组,所以dp只有[j]这一维.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct E{
	int num,tim;
	bool operator < (const E& x)const{
		if(num==x.num) return tim<x.tim;
		return num<x.num;
	}
}dp[10005];
int n,t,a[55];
int main()
{
	int T,i,j,sum,Case=0;
	scanf("%d",&T);
	while(T--){
		Case++;
		sum=0;
		memset(dp,0,sizeof(dp));
		scanf("%d%d",&n,&t);
		for(i=1;i<=n;i++){
			scanf("%d",&a[i]);
			sum+=a[i];
		}
		t=min(t-1,sum);
		for(i=1;i<=n;i++){
			for(j=t;j>=a[i];j--){
				E tmp;
				tmp.num=dp[j-a[i]].num+1;
				tmp.tim=dp[j-a[i]].tim+a[i];
				if(dp[j]<tmp){
					dp[j]=tmp;
				}
			}
		}
		printf("Case %d: %d %d\n",Case,dp[t].num+1,dp[t].tim+678);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值