这题看了龙教主的报告才会做 Orz
http://acmicpc.org.cn/wiki/index.php?title=2009_Northwestern_Europe_Mountain_Road_Solution
/*
题意:一条单向的公路 两端某些时刻有车过来
给出这些车到达公路端的时间arrive,还有这些车通过这条公路的最短时间run
要求相继通过某个点的两辆车时间不能少于10,也不能超车,而且不能打乱车来的顺序
问怎么安排,使得最后通过公路的那辆车的时间最短
题目给的限制具有顺序性,应想到dp
dpA[i,j],dpB[i,j]分别表示两边刚好走了i,j辆车的最短时间,A刚走完,B刚走完
转移的话枚举这某连续走K部车!!
重要的是要理清车怎么跑:
起始时间st = max(车到桥的时间T , 上一部车出发后+10)
到达时间ed = max(车出发后全速前进 , 上一部车到达后+10)
这样就保证了 “2车通过同一个点的时间间隔要至少是10秒” !!
那么此时车行驶时间是ed-st
启示:这里枚举连续走K部车,跟现实世界一样,放多少部车走
*/
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 210;
const int INF = 1000000000;
struct Car
{
int st,run;
};
int dpA[MAXN][MAXN],dpB[MAXN][MAXN];
Car carA[MAXN],carB[MAXN];
int main()
{
//freopen("in","r",stdin);
int T;
for(scanf("%d",&T);T--;)
{
int n,na=0,nb=0;
char ch;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf(" %c",&ch);
if(ch=='A')
{
na++;
scanf("%d%d",&carA[na].st,&carA[na].run);
}
else
{
nb++;
scanf("%d%d",&carB[nb].st,&carB[nb].run);
}
}
//[i,j] -> [k,j]
//[i,j] -> [i,k]
for(int i=0;i<=na;i++)
for(int j=0;j<=nb;j++)
dpA[i][j]=dpB[i][j]=INF;
dpA[0][0]=dpB[0][0]=0;
for(int i=0;i<=na;i++)
for(int j=0;j<=nb;j++)
{
if(dpB[i][j]!=INF)
{
int st = max(carA[i+1].st,dpB[i][j]);
int ed = st + carA[i+1].run;
dpA[i+1][j] = min(dpA[i+1][j],ed);
for(int k=i+2;k<=na;k++)
{
st = max(st+10,carA[k].st);//must more than st+10
ed = max(st+carA[k].run,ed+10);//must more than ed+10
dpA[k][j] = min(dpA[k][j],ed);
}
}
if(dpA[i][j]!=INF)
{
int st = max(carB[j+1].st,dpA[i][j]);
int ed = st + carB[j+1].run;
dpB[i][j+1] = min(dpB[i][j+1],ed);
for(int k=j+2;k<=nb;k++)
{
st = max(st+10,carB[k].st);//must more than st+10
ed = max(st+carB[k].run,ed+10);//must more than ed+10
dpB[i][k] = min(dpB[i][k],ed);
}
}
}
printf("%d\n",min(dpA[na][nb],dpB[na][nb]));
}
return 0;
}