EOJ:Crossing the Road
——从地图左下角到右上角需要最短的时间(有交通灯)
——搜索
——url:http://202.120.106.94/onlinejudge/problemshow.php?pro_id=446
——source:Google Code Jam
————————————————————————————————————————————————
一开始以为只可能往上和往右走,于是直接DP。
事实上由于红灯时间很长,可以绕个来回。
本题灯的熄灭时间存储比较麻烦
另外算路口通过的时间是用求模运算会快很多
#include<stdio.h> #include<queue> using namespace std; #define MAXM 100 #define oo 100000000000000000LL const int dx[4] = { 0, 1, 0, -1 }; const int dy[4] = { 1, 0, -1, 0 }; struct node { int x, y; long long t; bool operator <(const node &b) const { return t > b.t; } node() { } node(int a, long long b, long long c) { x = a; y = b; t = c; } } u, v; long long T[MAXM][MAXM]; long long TIME[MAXM][MAXM][3]; int n, m, C; void readin() { int i, j, k; scanf("%d%d", &n, &m); for (i = 0; i < n; i++) for (j = 0; j < m; j++) { for (k = 0; k < 3; k++) scanf("%lld", &TIME[n - i - 1][j][k]); TIME[n - i - 1][j][2] %= (TIME[n - i - 1][j][0] + TIME[n - i - 1][j][1]); } } long long min(long a, long long b) { return a < b ? a : b; } void work() { int i, j; long long N, W, t, tmp; priority_queue<node> q; for (i = 0; i <= 2 * n; i++) for (j = 0; j <= 2 * m; j++) T[i][j] = oo; T[0][0] = 0; q.push(node(0, 0, 0)); while (!q.empty()) { u = q.top(); q.pop(); if (u.t > T[u.x][u.y]) continue; if (u.x == 2 * n - 1 && u.y == 2 * m - 1) break; N = TIME[u.x / 2][u.y / 2][0]; W = TIME[u.x / 2][u.y / 2][1]; t = TIME[u.x / 2][u.y / 2][2]; for (i = 0; i < 4; i++) { v.x = u.x + dx[i]; v.y = u.y + dy[i]; if (v.x < 0 || v.x >= 2 * n || v.y < 0 || v.y >= 2 * m) continue; if (((u.y % 2 == 1) && (i == 0)) || ((v.y % 2 == 1) && (i == 2)) //不过马路 || ((u.x % 2 == 1) && (i == 1)) || ((v.x % 2 == 1) && (i == 3))) v.t = u.t + 2; else if (i == 1 || i == 3) { tmp = t; tmp = (tmp - (u.t) % (N + W) + N + W) % (N + W) + u.t; //过马路南北方向走 if (tmp - (N + W) <= u.t && tmp - W >= u.t + 1) v.t = u.t + 1; else if (N >= 1) v.t = tmp + 1; } else { tmp = t + N; tmp = (tmp - (u.t) % (N + W) + N + W) % (N + W) + u.t; //过马路东西方向走 if (tmp - (N + W) <= u.t && tmp - N >= u.t + 1) v.t = u.t + 1; else if (W >= 1) v.t = tmp + 1; } if (v.t < T[v.x][v.y]) { T[v.x][v.y] = v.t; q.push(v); } } } printf("%lld\n", T[2 * n - 1][2 * m - 1]); } int main() { int i; scanf("%d", &C); for (i = 1; i <= C; i++) { readin(); printf("Case #%d: ", i); work(); } return 0; }