#include #include #include #include #include #include #include #include #include #include using namespace std; typedef long long Int; typedef pair PII; typedef vector VInt; #define FOR(a, b, c) for(a = (b); a < (c); ++a) #define MP make_pair #define TL 4 #define RUN_MOD 100 #define SZ 256 #define MAX (100 << 10) #define INF (1LL << 60) const int DR[] = { -1, 1, 0, 0 }; const int DC[] = { 0, 0, -1, 1 }; const char DZ[] = { 'U', 'D', 'L', 'R' }; struct Bakery { int row, col; } Bakeries[MAX]; struct Party { int row, col; int start, duration; } Parties[MAX]; int partyCmp(const Party& a, const Party& b) { return a.start + a.duration < b.start + b.duration; } int H[SZ][SZ]; Int Time[SZ][SZ]; int Dir[SZ][SZ]; Int Time2[SZ][SZ]; int Dir2[SZ][SZ]; int Max[MAX]; int Min[MAX]; int gN, gP, gK; Int stepTime(int h1, int h2, int cakes) { Int r = abs(h1 - h2) + cakes; return r*r + 1; } void f(int row, int col, Int time) { int i, j; FOR(i, 0, gN) FOR(j, 0, gN) Time[i][j] = INF; priority_queue> q; Time[row][col] = time; Dir[row][col] = -1; q.push(MP(-Time[row][col], PII(row, col))); while (!q.empty()) { Int val = -q.top().first; int r = q.top().second.first; int c = q.top().second.second; q.pop(); if (val != Time[r][c]) continue; FOR(i, 0, 4) { int rr = r + DR[i]; int cc = c + DC[i]; if (rr < 0 || gN <= rr || cc < 0 || gN <= cc) continue; Int vv = val + stepTime(H[r][c], H[rr][cc], 0); if (vv < Time[rr][cc]) { Time[rr][cc] = vv; Dir[rr][cc] = i; q.push(MP(-Time[rr][cc], PII(rr, cc))); } } } } Int g(int cakes, int party) { int i, j; FOR(i, 0, gN) FOR(j, 0, gN) Time2[i][j] = INF; priority_queue> q; FOR(i, 0, gK) { int r = Bakeries[i].row; int c = Bakeries[i].col; Time2[r][c] = Time[r][c]; Dir2[r][c] = -1; q.push(MP(-Time2[r][c], PII(r, c))); } while (!q.empty()) { Int val = -q.top().first; int r = q.top().second.first; int c = q.top().second.second; q.pop(); if (val != Time2[r][c]) continue; FOR(i, 0, 4) { int rr = r + DR[i]; int cc = c + DC[i]; if (rr < 0 || gN <= rr || cc < 0 || gN <= cc) continue; Int vv = val + stepTime(H[r][c], H[rr][cc], cakes); if (vv < Time2[rr][cc]) { Time2[rr][cc] = vv; Dir2[rr][cc] = i; q.push(MP(-Time2[rr][cc], PII(rr, cc))); } } } FOR(i, 0, gP) if (Time2[Parties[i].row][Parties[i].col] <= Parties[i].start) Min[i] = max(Min[i], cakes); else Max[i] = min(Max[i], cakes); Int res = 0; FOR(i, party, party + 1) { Int t = Parties[i].start + Parties[i].duration - Time2[Parties[i].row][Parties[i].col]; if (t > Parties[i].duration) t = Parties[i].duration; if (t > 0) { Int v = t * (cakes + 1); if (res < v) res = v; } } return res; } void solve() { int N, P, K; scanf("%d%d%d", &N, &P, &K); gN = N; gP = P; gK = K; int i, j; FOR(i, 0, N) FOR(j, 0, N) scanf("%d", &H[i][j]); int homeRow, homeCol; scanf("%d%d", &homeRow, &homeCol); --homeRow; --homeCol; FOR(i, 0, P) { int r, c, s, d; scanf("%d%d%d%d", &r, &c, &s, &d); --r; --c; --s; Parties[i].row = r; Parties[i].col = c; Parties[i].start = s; Parties[i].duration = d; } FOR(i, 0, K) { int r, c; scanf("%d%d", &r, &c); --r; --c; Bakeries[i].row = r; Bakeries[i].col = c; } sort(Parties, Parties + P, partyCmp); Int time = 0; int row = homeRow; int col = homeCol; time_t startTime = clock(); Int score = 0; Int runCnt = 0; Int checkCnt = 0; bool timeout = false; while (!timeout) { f(row, col, time); FOR(i, 0, P) { Min[i] = -1; Max[i] = (1 << 15) - 1; } vector> v; FOR(i, 0, P) if (Parties[i].start + Parties[i].duration > time) { Int t = Parties[i].duration; if (time > Parties[i].start) t -= time - Parties[i].start; v.push_back(MP(t, i)); } sort(v.begin(), v.end()); int cnt = v.size(); Int best = 0; int bestCakes = 0; int bestParty = 0; for (i = cnt - 1; i >= 0; --i) { Int t = v[i].first; int party = v[i].second; Int need = best / t + 1; if (Max[party] < need) continue; if (Min[party] < need) { ++runCnt; if (runCnt % RUN_MOD == 0) { ++checkCnt; if ((clock() - startTime + 0.0) / CLOCKS_PER_SEC > TL) { timeout = true; break; } } Int r = g(need, party); if (r == 0) continue; Min[party] = need; if (r > best) { best = r; bestCakes = need; bestParty = party; } } while (Max[party] - Min[party] > 1) { ++runCnt; if (runCnt % RUN_MOD == 0) { ++checkCnt; if ((clock() - startTime + 0.0) / CLOCKS_PER_SEC > TL) { timeout = true; break; } } int mid = (Max[party] + Min[party]) / 2; Int r = g(mid, party); if (r > best) { best = r; bestCakes = mid; bestParty = party; } } if (timeout) break; if (bestParty == party) { int am = bestCakes; while (true) { ++runCnt; if (runCnt % RUN_MOD == 0) { ++checkCnt; if ((clock() - startTime + 0.0) / CLOCKS_PER_SEC > TL) { timeout = true; break; } } ++am; Int r = g(am, party); if (r > best) { best = r; bestCakes = am; bestParty = party; } else break; } } } if (best == 0) break; g(bestCakes, bestParty); int p = bestParty; int r = Parties[p].row; int c = Parties[p].col; VInt moves; while (Dir2[r][c] != -1) { int d = Dir2[r][c]; moves.push_back(d); r -= DR[d]; c -= DC[d]; } if (bestCakes != 0) moves.push_back(-bestCakes); while (Dir[r][c] != -1) { int d = Dir[r][c]; moves.push_back(d); r -= DR[d]; c -= DC[d]; } reverse(moves.begin(), moves.end()); FOR(i, 0, moves.size()) if (moves[i] < 0) printf("%d", -moves[i]); else printf("%c", DZ[moves[i]]); Int arrive = Time2[Parties[p].row][Parties[p].col]; FOR(i, 0, P) if(Parties[i].row == Parties[p].row && Parties[i].col == Parties[p].col && Parties[i].start + Parties[i].duration > arrive && Parties[i].start <= Parties[p].start) printf("+"); if (bestCakes != 0) printf("%d", bestCakes); score += best; row = Parties[p].row; col = Parties[p].col; time = Parties[p].start + Parties[p].duration; } printf("\n"); fprintf(stderr, "score = %lld\n", score); fprintf(stderr, "timeout = %s\n", timeout ? "yes" : "no"); fprintf(stderr, "runs = %lld\n", runCnt); fprintf(stderr, "checks = %lld\n", checkCnt); } int main() { freopen("party.in", "r", stdin); freopen("party.out", "w", stdout); solve(); return 0; }