[NOIP模拟赛]越唱越勇

题目描述

有一个歌手,他有 n 首歌可以唱,第 i 首歌有一个所需时间 duration[i] 和声调 tone[i]。本题的歌曲从0~n-1编号。 如果歌手在唱声调为 y 的歌之前的最后一首歌声调为 x,那么他需要额外 |x-y| 的时间调整声调。求在 T 的时间内最多唱几首歌。


输入格式
第1行:1个整数n,表示歌曲的数量(1≤n≤50)
第2行:n个整数,表示数组duration[ ]
第3行:n个整数,表示数组tone[ ](1≤duration[ ],tone[ ]≤10^5)

第4行:1个整数T(1≤T≤10^7)


输出格式

第1行:1个整数,表示答案


输入样例
4
3 5 4 11
2 1 3 1

17


输出样例

3


样例说明

不可能在给定的时间内唱出所有的4首歌,即使没有变调的停顿,所有歌曲的总长度都超过了17个单位的时间。最多唱3首歌的一种方案是:首先,用3个单位的时间唱歌曲0。等待| 2 - 3 | = 1单位时间,然后以4个单位的时间唱歌曲2。等待| 3 - 1 | = 2单位时间,然后以5个单位的时间唱出歌曲1。总时间是3 + 1 + 4 + 2 + 5 = 15单位时间。



题解:dp[i][j]: 唱i首歌, 最后一首为j, 所花的时间


#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=55;

int n, T, sum;
int dp[N][N];
struct node{ int du, tn; } sng[N];
bool cmp( node a, node b ) {
	if( a.tn!=b.tn ) return a.tn<b.tn;
	return a.du<b.du;
}

int main() {
	scanf( "%d", &n );
	for( int i=1; i<=n; i++ ) scanf( "%d", &sng[i].du );
	for( int i=1; i<=n; i++ ) scanf( "%d", &sng[i].tn );
	sort( sng+1, sng+n+1, cmp );
	scanf( "%d", &T );
	
	memset( dp, 0x3f, sizeof dp );
	for( int i=1; i<=n; i++ ) {
		dp[1][i]=sng[i].du;
		if( dp[1][i] ) sum=1;
	}
	
	for( int i=2; i<=n; i++ )
		for( int j=i; j<=n; j++ ) {
			for( int k=1; k<j; k++ )
				dp[i][j]=min( dp[i][j], dp[i-1][k]+sng[j].du+sng[j].tn-sng[k].tn );
			if( dp[i][j]<=T ) sum=i;
		}
	
	printf( "%d\n", sum );
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值