POJ - 3846 Mountain Road 动归
题意:n个人要过桥,有的人从左边来,有的人从右边来,给你他们到达桥一端的时间和过桥所需要的时间,要求相向而行的只能有一人,对于每一个点,不能在10s内有同向而行的人经过。
思路:f[i][j][A/B] 表示 从左边走了i个,从右边走了j个,最后一个是左边还是右边的最小时间。问你最后一辆车的到达时间最小是多少。
对于每一个这样的状态,可以往后面一直推过了k辆反向的车所消耗的时间,只要把出发时间和到达时间的间距都压在10s以上就可以满足条件,不断的更新最优值就行了。
我之前写的时候对于每一个状态只知道推相邻的状态,这样导致转移的代码特别冗杂,最终答案也没有对,而且还超时了,所以这题来讲还是很遗憾没写出来,想到了状态,只是转移的时候犯了错误,没能过掉。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define LL long long 6 #define INF 0x3f3f3f3f 7 #define IN freopen("in.txt","r",stdin) 8 #define OUT freopen("out.txt", "w", stdout) 9 #define MAXN 100005 10 using namespace std; 11 #define A 0 12 #define B 1 13 struct Node{ 14 int x, y, pos; 15 }; 16 int n; 17 int f[205][205][2]; 18 Node a[205], b[205]; 19 int a0, b0; 20 int main() 21 { 22 //IN; 23 //OUT; 24 int T; 25 scanf("%d", &T); 26 while(T--){ 27 scanf("%d\n", &n); 28 char ch; 29 int x, y; 30 a0 = 0; 31 b0 = 0; 32 //scanf("%c", &ch); 33 for(int i = 1; i <= n; i++){ 34 scanf("%c", &ch); 35 scanf("%d%d\n", &x, &y); 36 37 if(ch == 'A'){ 38 a0++; 39 a[a0].x = x; 40 a[a0].y = y; 41 a[a0].pos = i; 42 } 43 else{ 44 b0++; 45 b[b0].x = x; 46 b[b0].y = y; 47 b[b0].pos = i; 48 } 49 } 50 int i = 0, j = 0; 51 memset(f, INF, sizeof(f)); 52 f[0][0][A] = 0; 53 f[0][0][B] = 0; 54 int s, t; 55 for(int i = 0; i <= a0; i++){ 56 for(int j = 0; j <= b0; j++){ 57 t = f[i][j][A] - 10; 58 s = f[i][j][A] - 10; 59 for(int k = j + 1; k <= b0; k++){ 60 s = max(s + 10, b[k].x); 61 t = max(t + 10, s + b[k].y); 62 f[i][k][B] = min(f[i][k][B], t); 63 } 64 t = f[i][j][B] - 10; 65 s = f[i][j][B] - 10; 66 for(int k = i + 1; k <= a0; k++){ 67 s = max(s + 10, a[k].x); 68 t = max(t + 10, s + a[k].y); 69 f[k][j][A] = min(f[k][j][A], t); 70 } 71 } 72 } 73 printf("%d\n", min(f[a0][b0][A], f[a0][b0][B])); 74 } 75 return 0; 76 }