這題看了龍教主的報(bào)告才會(huì)做 Orz
http://acmicpc.org.cn/wiki/index.php?title=2009_Northwestern_Europe_Mountain_Road_Solution
/*
題意:一條單向的公路 兩端某些時(shí)刻有車過來
給出這些車到達(dá)公路端的時(shí)間arrive,還有這些車通過這條公路的最短時(shí)間run
要求相繼通過某個(gè)點(diǎn)的兩輛車時(shí)間不能少于10,也不能超車,而且不能打亂車來的順序
問怎么安排,使得最后通過公路的那輛車的時(shí)間最短
題目給的限制具有順序性,應(yīng)想到dp
dpA[i,j],dpB[i,j]分別表示兩邊剛好走了i,j輛車的最短時(shí)間,A剛走完,B剛走完
轉(zhuǎn)移的話枚舉這某連續(xù)走K部車!!
重要的是要理清車怎么跑:
起始時(shí)間st = max(車到橋的時(shí)間T , 上一部車出發(fā)后+10)
到達(dá)時(shí)間ed = max(車出發(fā)后全速前進(jìn) , 上一部車到達(dá)后+10)
這樣就保證了 “2車通過同一個(gè)點(diǎn)的時(shí)間間隔要至少是10秒” ??!
那么此時(shí)車行駛時(shí)間是ed-st
啟示:這里枚舉連續(xù)走K部車,跟現(xiàn)實(shí)世界一樣,放多少部車走
*/
#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;
}