牛客网哈尔滨工程大学第十四届程序设计竞赛(同步赛)——D 简单的烦恼(DP)

本文介绍了一种使用动态规划(DP)解决背包问题的方法,通过构建状态dp[i,j]表示前i首歌在j分钟内可听的总时长,利用状态转移方程实现最优解的寻找,最终达到在给定时间内播放最长歌曲总时长的目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题可以用DP来做,实质上是个背包模型,因为它有一个费用t。
状态:dp[i,j]表示前i首歌,在j分钟内可以听的歌曲的总时长。
状态转移方程:
dp[i,j]=
if(j<song[i]) dp[i-1,j];
else max(dp[i-1,j],dp[i-1,j-song[i]]+song[i]);
在这里要注意一下:因为我们要选出最接近时间t的歌曲的时间总和sum(不能>=t),然后sum+max(song[i]),这样才可以使时间最长。因此j的范围是[song[i],t-1]。
这里的j和dp[i,j]所表示的意义都是时间,说明背包中DP对象以及DP意义的物理意义是可以一样——其实只要有费用,就可以想到用背包模型来做。

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
typedef long long ll;
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=8e4+5;
int dp[maxn],s[205];			//用了滚动数组
int main()
{
	int T,n,t,i,j;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&t);
		memset(dp,0,sizeof(dp));
		for(i=1;i<=n;i++)
			scanf("%d",&s[i]);
		sort(s+1,s+1+n);
		dp[0]=0;
		for(i=1;i<=n-1;i++)		//i止于n-1
			for(j=t-1;j>=s[i];j--)
				dp[j]=max(dp[j],dp[j-s[i]]+s[i]);
		printf("%d\n",dp[t-1]+s[n]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值