题目描述
有一个歌手,他有 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; }