比赛得时候想的很复杂,以为是个贪心…

还是很考验思维得啊…

Ⅰ . 由 于 A l i c e 写 完 了 x 题 一 定 是 等 B o b 写 完 了 才 交 ( 浪 费 B o b 时 间 ) Ⅰ.由于Alice写完了x题一定是等Bob写完了才交(浪费Bob时间) .AlicexBob(Bob)

若 A l i c e 选 择 不 写 x 题 , B o b 会 写 完 x 题 若Alice选择不写x题,Bob会写完x题 Alicex,Bobx

所 以 我 们 可 怜 的 B o b 一 定 是 从 头 到 尾 老 老 实 实 写 每 一 道 题 \color{Red}所以我们可怜的Bob一定是从头到尾老老实实写每一道题 Bob


Ⅱ . 根 据 Ⅰ , 只 要 A l i c e 在 ∑ i = 1 i = p b [ i ] 时 间 内 写 完 第 p 题 , 就 可 以 拿 下 分 数 Ⅱ.根据Ⅰ,只要Alice在\sum_{i=1}^{i=p}b[i]时间内写完第p题,就可以拿下分数 .,Alicei=1i=pb[i]p,

Ⅲ . 设 A l i c e 最 后 写 的 题 集 合 是 y . Ⅲ.设Alice最后写的题集合是y. .Alicey.

那 么 A l i c e 一 定 是 从 小 到 大 得 顺 序 来 写 y 集 合 中 的 题 那么Alice一定是从小到大得顺序来写y集合中的题 Alicey

根据以上三点,一个很明显的DP出来了

定 义 d p [ i ] [ j ] 为 前 i 题 得 j 分 花 费 的 最 小 时 间 定义dp[i][j]为前i题得j分花费的最小时间 dp[i][j]ij

转 移 就 是 决 策 第 i 题 写 不 写 转移就是决策第i题写不写 i

#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[2009],t,n,b[2009],pre[2009],ans,dp[2009][2009];
signed main()
{
	cin >> t;
	while( t-- )
	{
		cin >> n;
		for(int i=0;i<=2000;i++)
		for(int j=0;j<=2000;j++)
			dp[i][j]=1e18;
		pre[0]=0,ans=0;
		for(int i=1;i<=n;i++)	cin >> a[i];
		for(int i=1;i<=n;i++)	cin >> b[i],pre[i]=pre[i-1]+b[i];
		//定义前i道题得j分得最小时间
		dp[0][0]=0;
		for(int i=1;i<=n;i++)
		{ 
			dp[i][0]=0;
			for(int j=1;j<=i;j++)
			{
				dp[i][j]=min(dp[i][j],dp[i-1][j]);
				int tim=dp[i-1][j-1]+a[i];//做第i题
				if( tim<=pre[i] )
					dp[i][j]=min(dp[i-1][j],tim); 
				if( dp[i][j]!=1e18 )	ans=max(ans,j);
			}
		}
		cout << ans << endl;
	}
}