這題看了龍教主的報(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;
}