#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxx = 180 * 55;
int t[55];//题目所给的歌的每个时长
struct Node{
int num, time;//歌的数量和时长
}dp[maxx];
int main()
{
int l;
int n, len, sum = 0;//len控制时长,sum为了判断所给的歌的总时长
int max_time;//为了判断所给len时长与sum大小
int cnt = 1;
scanf("%d", &l);
while(l--){
scanf("%d%d", &n, &len);
memset(dp, 0, sizeof(dp));
memset(t, 0, sizeof(t));
for(int i = 1; i <= n; i++) {scanf("%d", &t[i]); sum += t[i];}
max_time = min(sum, len - 1);//最多也是时长限制-1
for(int i = 1; i <= n; i++){
for(int j = max_time; j >= t[i]; j--){
Node s; //这里用Node 其实就是降维度的一个写法,从max_time to t[i]这种写法可以降维度其实和最简单的01背包相同
s.num = dp[j-t[i]].num + 1;//这里一定记得搞清楚是”前“i件物品(歌)的总和,自己不懂可以推一下
s.time = dp[j-t[i]].time + t[i];
if(dp[j].num < s.num){//这个题歌的数量优先 dp[j]表示当前容量下的个数,s.num表示前i首歌的总个数
dp[j].num = s.num;
dp[j].time = s.time;
}
else if(dp[j].num == s.num && dp[j].time < s.time){//相同个数的歌需要保证最长时间
dp[j].num = s.num;
dp[j].time = s.time;
}
}
}
cout <<"Case " << cnt++ << ": " << dp[max_time].num + 1 << " " << dp[max_time].time + 678 << endl << max_time;//这里+1的原意是结构体初始化为0
//其实博主刚开始很诧异为什m最终最多的个数会更新到max_time上,这是由于第一个if,自己不懂过程的一定自己在纸上推一下,懂过程以后代码就显得简单了
}
return 0;
}
uva12563 Jin Ge Jin Qu
最新推荐文章于 2021-02-11 16:29:33 发布