// C++ implementation of Juggling Tramps (Problem E ACM SP 1999) // #include #include using namespace std; static char s[] = "00:00"; // char* hhmm(int tm) { int h = tm / 60; int m = tm % 60; s[0]= '0'+ h/10; s[1]= '0'+ h%10; s[3]= '0'+ m/10; s[4]= '0'+ m%10; return s; } struct cell // for dynammic programme { cell() { atime = 0; dir = NONE; } int atime; // arrived time enum { NORTH, EAST, NONE } dir; // direction arrived }; int const MAXROADS = 100; inline int at(int i, int j) { return (i-1)*MAXROADS + (j-1); } int t, m; // negative if no such time for next tram int nextSouth(int first, int cnt, int dist, const cell &ac) { int tm = ac.atime; if (ac.dir == cell::NORTH) return tm; // keep going on same tram if (tm > first + (dist-1)*m + (cnt-1)*t) return -1; // missed last one #if 0 int ride = first + (dist-1)*m; while (ride < tm) ride += t; return ride; #else int knt = (tm - first - (dist-1)*m + t-1)/t; return first + (dist-1)*m + knt*t; #endif } // int nextWest(int first, int cnt, int dist, const cell &ac) { int tm = ac.atime; if (ac.dir == cell::EAST) return tm; // keep going on same tram if (tm > first + (dist-1)*m + (cnt-1)*t) return -1; // missed last one #if 0 int ride = first + (dist-1)*m; while (ride < tm) ride += t; return ride; #else int knt = (tm - first - (dist-1)*m + t-1)/t; return first + (dist-1)*m + knt*t; #endif } int main() { while (true) { cin >> t >> m; // interval time t and minutes to travel m if (t == 0 && m == 0) break; int n, e; // north-south (x) and east-west (y) roads cin >> n >> e; int sx, sy, fx, fy; // starting and finish points cin >> sx >> sy >> fx >> fy; int tm; // starting time cin >> tm; int tmp1, tmp2; vector n_first(n+1); // read in north-south schedule vector n_k(n+1); for (int i=1; i<=n; i++) { cin >> tmp1 >> tmp2; n_first[i] = tmp1; n_k[i] = tmp2; } vector e_first(n+1); // read in east-west schedule vector e_k(n+1); for (int i=1; i<=e; i++) { cin >> tmp1 >> tmp2; e_first[i] = tmp1; e_k[i] = tmp2; } cell dp[MAXROADS*MAXROADS]; dp[at(sx,sy)].atime = tm; // ignore direction at start dp[at(fx,fy)].dir = cell::NONE; // can't get to final yet int westTramTm = nextWest(e_first[sy], e_k[sy], sx, dp[at(sx,sy)]); int i; for (i=sx+1; i<=fx; i++) // fill first row of d.p. { if (westTramTm > 0) { dp[at(i,sy)].atime = westTramTm + (i-sx) * m; dp[at(i,sy)].dir = cell::EAST; } else dp[at(i,sy)].dir = cell::NONE; } int southTramTm = nextSouth(n_first[sx], n_k[sx], sy, dp[at(sx,sy)]); for (i=sy+1; i<=fy; i++) // fill first column of d.p. { if (southTramTm > 0) { dp[at(sx,i)].atime = southTramTm + (i-sy) * m; dp[at(sx,i)].dir = cell::NORTH; } else dp[at(sx,i)].dir = cell::NONE; } // complete the dynammic programme table // int x, y; for (x = sx+1; x<=fx; x++) for (y = sy+1; y<=fy; y++) { if (dp[at(x-1,y)].dir != cell::NONE) westTramTm = nextWest(e_first[y], e_k[y], x-1, dp[at(x-1,y)]); else westTramTm = -1; if (dp[at(x,y-1)].dir != cell::NONE) southTramTm = nextSouth(n_first[x], n_k[x], y-1, dp[at(x,y-1)]); else southTramTm = -1; if (westTramTm > 0 && southTramTm > 0) { if (westTramTm < southTramTm) { dp[at(x,y)].atime = westTramTm + m; dp[at(x,y)].dir = cell::EAST; } else { dp[at(x,y)].atime = southTramTm + m; dp[at(x,y)].dir = cell::NORTH; } } else if (westTramTm > 0) { dp[at(x,y)].atime = westTramTm + m; dp[at(x,y)].dir = cell::EAST; } else if (southTramTm > 0) { dp[at(x,y)].atime = southTramTm + m; dp[at(x,y)].dir = cell::NORTH; } else { dp[at(x,y)].dir = cell::NONE; } } // for x and y if (dp[at(fx,fy)].dir != cell::NONE || (sx==fx && sy==fy)) { cout << "You arrive at " << hhmm(dp[at(fx,fy)].atime) << ".\n"; } else cout << "Impossible.\n"; #if 0 /* debugging table */ for (y = sy; y<=fy; y++) { for (x = sx; x<=fx; x++) { cerr << dp[at(x,y)].atime << ' '; } cerr << endl; } #endif } // while }