这题看了龙教主的报告才会做 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 ;
}