南邮 OJ 2000 水獭

本文探讨了一只热爱动漫的水獭如何在有限时间内观看尽可能多的动漫集数的问题。采用动态规划算法解决,考虑了多部动漫的不同集数长度及其累计观看时间。

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

水獭

时间限制(普通/Java) : 1500 MS/ 5000 MS          运行内存限制 : 65536 KByte
总提交 : 93            测试通过 : 24 

比赛描述

某只水獭酷爱动漫,但是看动画片是很耗时间的,以至于没时间刷题了都。于是,他给她下了个限定,每天只能看T秒的动画片。但是,她今天想看的动画片很多很多,目测在时限内肯定看不完了,只好先计划一下,在时限内看的尽可能多。
水獭想看的动漫有N部,其中每一部都有若干集(第1集、第2集……)这些剧集的观看顺序是不可以调换的,即看完第1集才能看第2集,看完第1、2集后才能看第3集。虽然不能调换顺序,但是她可以选择看到任意一集后放弃这部作品而不用将该部的所有剧集看完。
还要注意的两点:
1、每一集都会完整的看完而不会中途间断。
2、“时限内看得尽可能多”,这是以“集”为单位进行评判的。
那么,请计算出她最多可以看多少集动漫呢?

输入

第一行包含一个正整数Q,表示有Q组测试数据(1≤Q≤10);
每组测试数据包含若干行,第一行包含两个正整数N和T,分别表示N部动漫作品(1≤N≤20)和T秒的时限(1≤T≤43200);
接下来N行,第i行先包含一个正整数Ki,表示第i部动漫有Ki集(1≤Ki≤20),紧跟着Ki个正整数Cj(1≤Cj≤5000),依次表示第1、2……集的时长(秒)。

输出

每组测试数据对应一行输出,每行输出仅包含一个整数,即水獭在时限内最多可以看动漫的集数。

样例输入

1
2 15
3 5 5 5
5 10 1 1 1 1

样例输出

5

题目来源

7A






/* Wrong Answer at Test 1
#include<iostream>
using namespace std;

#define MAX_T 43200
int dp[MAX_T + 1];		// dp[i] 表示话费 i 秒最多可以看多少集

#define MAX_K 20
int C[MAX_K];			// 第 i 集的时长,或者前 i 集的时长总和

int main(){
	int Q, N, T, i, K;
	scanf("%d", &Q);
	while(Q--){
		scanf("%d %d", &N, &T);
		memset(dp, 0, sizeof(dp));
		while(N--){
			scanf("%d", &K);
			for(i = 1; i <= K; ++i){
				scanf("%d", C + i);
				C[i] += C[i - 1];
				if(C[i] <= T){
					dp[T] = max(dp[T], i + dp[T - C[i]]);
				}
			}
			for(i = 1; i <= K && C[i] <= T; ++i){
				dp[C[i]] = max(dp[C[i]], i);
			}
		}
		printf("%d\n", dp[T]);
	}
}
*/


/*
#include<iostream>
using namespace std;

#define MAX_T 43200
int dp[MAX_T + 1];		// dp[i] 表示话费 i 秒最多可以看多少集

#define MAX_K 20
int C[MAX_K];			// 第 i 集的时长,或者前 i 集的时长总和

int main(){
	int Q, N, T, i, K;
	scanf("%d", &Q);
	while(Q--){
		scanf("%d %d", &N, &T);
		memset(dp, 0, sizeof(dp));
		while(N--){
			scanf("%d", &K);
			for(i = 1; i <= K; ++i){
				scanf("%d", C + i);
				C[i] += C[i - 1];
				if(C[i] <= T){
					dp[T] = max(dp[T], i + dp[T - C[i]]);
				}
			}
			for(i = 1; i <= K && C[i] <= T; ++i){
				dp[C[i]] = max(dp[C[i]], i);
			}
			for(i = 2; i <= T ; i++){
				dp[i] = max(dp[i - 1], dp[i]);
			}
		}
		printf("%d\n", dp[T]);
	}
}

*/



/* AC 312MS
#include<iostream>
using namespace std;

#define MAX_T 43200
int dp[MAX_T + 1];		// dp[i] 表示话费 i 秒最多可以看多少集
int dp2[MAX_T + 1];		// dp[i] 表示话费 i 秒最多可以看多少集

#define MAX_K 20
int C[MAX_K];			// 第 i 集的时长,或者前 i 集的时长总和

int main(){
//	freopen("test.txt", "r", stdin);
	int Q, N, T, i, K;
	scanf("%d", &Q);
	while(Q--){
		scanf("%d %d", &N, &T);
		memset(dp, 0, sizeof(dp));
		memset(dp2, 0, sizeof(dp2));
		while(N--){
			scanf("%d", &K);
			for(i = 1; i <= K; ++i){
				scanf("%d", C + i);
				C[i] += C[i - 1];
				for(int j = T; j >= C[i]; j--){
					dp2[j] = max(dp2[j], max(dp[j], i + dp[j - C[i]]));
				}
			}
			for(i = 1; i <= T; ++i){
				dp[i] = dp2[i];
			}
//			for(i = 2; i <= T ; i++){
//				dp[i] = max(dp[i - 1], dp[i]);
//			}
		}
		printf("%d\n", dp[T]);
	}
}
*/


/* AC 296MS
#include<iostream>
using namespace std;

#define MAX_T 43200
int dp[MAX_T + 1];		// dp[i] 表示话费 i 秒最多可以看多少集
int dp2[MAX_T + 1];		// dp[i] 表示话费 i 秒最多可以看多少集

#define MAX_K 20
int C[MAX_K];			// 第 i 集的时长,或者前 i 集的时长总和

int main(){
//	freopen("test.txt", "r", stdin);
	int Q, N, T, i, K;
	scanf("%d", &Q);
	while(Q--){
		scanf("%d %d", &N, &T);
		memset(dp, 0, sizeof(int)*(T+1));
		memset(dp2, 0, sizeof(int)*(T+1));
		while(N--){
			scanf("%d", &K);
			for(i = 1; i <= K; ++i){
				scanf("%d", C + i);
				C[i] += C[i - 1];
				for(int j = T; j >= C[i]; j--){
					dp2[j] = max(dp2[j], max(dp[j], i + dp[j - C[i]]));
				}
			}
			memcpy(dp, dp2, sizeof(int)*(T+1));
		}
		printf("%d\n", dp[T]);
	}
}
*/



/* AC 187 MS
#include<iostream>
using namespace std;

#define MAX_T 43200
int dp[MAX_T + 1];		// dp[i] 表示话费 i 秒最多可以看多少集
int dp2[MAX_T + 1];		// dp[i] 表示话费 i 秒最多可以看多少集

#define MAX_K 20
int C[MAX_K];			// 第 i 集的时长,或者前 i 集的时长总和

int main(){
//	freopen("test.txt", "r", stdin);
	int Q, N, T, i, K;
	scanf("%d", &Q);
	while(Q--){
		scanf("%d %d", &N, &T);
		memset(dp, 0, sizeof(int)*(T+1));
		memset(dp2, 0, sizeof(int)*(T+1));
		while(N--){
			scanf("%d", &K);
			for(i = 1; i <= K; ++i){
				scanf("%d", C + i);
				C[i] += C[i - 1];
				for(int j = T; j >= C[i]; j--){
					dp2[j] = max(dp2[j], i + dp[j - C[i]]);
				}
			}
			memcpy(dp, dp2, sizeof(int)*(T+1));
		}
		printf("%d\n", dp[T]);
	}
}
*/



#include<iostream>
using namespace std;

#define MAX_T 43200
int dp[MAX_T + 1];
int dp2[MAX_T + 1];
#define MAX_K 20
int C[MAX_K];

int main(){
	int Q, N, T, i, K;
	scanf("%d", &Q);
	while(Q--){
		scanf("%d %d", &N, &T);
		memset(dp, 0, sizeof(dp));
		memset(dp2, 0, sizeof(dp2));
		while(N--){
			scanf("%d", &K);
			for(i = 1; i <= K; ++i){
				scanf("%d", C + i);
				C[i] += C[i - 1];
				for(int j = T; j >= C[i]; j--){
					dp2[j] = max(dp2[j], i + dp[j - C[i]]);
				}
			}
			memcpy(dp, dp2, sizeof(dp));
		}
		printf("%d\n", dp[T]);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值