题意:
有一条道,只能走一辆车,然后车有正向反向,正向的车至少隔10才能再开同方向的车,反向的不能同时开
思路;
d[i][j][0],d[i][j][1]分别表示在开了这么多辆的正向和反向后最后一辆是正向是反向的最少时间
那么,在交叉讨论之后同方向枚举是可以得到所有交叉情况,
那么对于同方向的车,开始时间至少是上个车的开始时间+10以及本量车的开始时间,结束时间至少是商量车的结束时间+10以及开始时间加耗费时间
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 222;
struct node {
int ar, len;
}lef[maxn], righ[maxn];
int d[maxn][maxn][2];
char str[maxn];
int n;
int main() {
int kase;
scanf("%d", &kase);
while(kase--) {
scanf("%d", &n);
int l=0, r=0;
int a, b;
for(int i=1; i<=n; i++) {
scanf("%s%d%d", str, &a, &b);
if(str[0] == 'A') {
l++;
lef[l].ar = a,lef[l].len=b;
}
else {
r++;
righ[r].ar=a, righ[r].len=b;
}
}
memset(d, 0x7f, sizeof(d));
d[0][0][0] = d[0][0][1] = 0;
for(int i=0; i<=l; i++)
for(int j=0; j<=r; j++) {
int st = d[i][j][1];
int ed = 0;
for(int k=i+1; k<=l; k++) {//实际上已经穿插了所有反向交叉形式
st = max(st, lef[k].ar);//反向车的结束时间
ed = max(st+lef[k].len, ed);
d[k][j][0] = min(d[k][j][0], ed);
st += 10;
ed += 10;
}
st = d[i][j][0];
ed = 0;
for(int k=j+1; k<=r; k++) {
st = max(st, righ[k].ar);//由于是反向的,所以一开始是不需要加上10的
ed = max(st+righ[k].len, ed);
d[i][k][1] = min(d[i][k][1], ed);
st += 10;//那么下一次就是同辆车,那么初始时间至少得是10
ed += 10;//那么结束时间也就至少是ed+10
}
}
int ans = min(d[l][r][1], d[l][r][0]);
printf("%d\n", ans);
}
return 0;
}