#include #include #include #include #include #include #include #include using namespace std; typedef long long lld; const int ALLTIME = 4700 * CLOCKS_PER_SEC / 1000; bool HaveTime() { return (clock() < ALLTIME); } struct QWE { int x, y; lld dist; bool operator<(const QWE& other)const { return dist > other.dist; } }; QWE GetQWE(int x, int y, lld dist) { QWE ret; ret.x = x; ret.y = y; ret.dist = dist; return ret; } struct Cord { int x, y; }; Cord GetCord(int x, int y) { Cord ret; ret.x = x; ret.y = y; return ret; } struct Party { int x, y, beg, dur, fin; bool operator<(const Party& other)const { return (beg != other.beg) ? begother.dur); } }; Party GetParty(int x, int y, int beg, int dur) { Party ret; ret.x = x; ret. y = y; ret.beg = beg; ret.dur = dur; ret.fin = beg+dur; return ret; } int mvx[4] = {1, -1, 0, 0}; int mvy[4] = {0, 0, 1, -1}; char otp[4] = {'D', 'U', 'R', 'L'}; int mvsz = 4; const double eps = 0.0000001; int N, P, K; int grid[202][202]; Cord home; Party parties[100002]; Cord sweets[202]; bool Legit(int x, int y) { return (x>=1&&x<=N && y>=1&&y<=N); } void Input() { cin >> N >> P >> K; ////cout<> grid[i][j]; } } int x, y; cin >> x >> y; home = GetCord(x, y); for (int i=1; i<=P; i++) { int beg, dur; cin >> x >> y >> beg >> dur; parties[i] = GetParty(x, y, beg, dur); } for (int i=1; i<=K; i++) { cin >> x >> y; sweets[i] = GetCord(x, y); } } lld Needed(int v1, int v2, int carry) { return (lld)(abs(v1-v2) + carry)*(lld)(abs(v1-v2) + carry) + 1LL; } char Direction(int x1, int y1, int x2, int y2) { for (int i=0; i pq; int UTFO[202][202], TFOkey; lld curdist[202][202]; char bestDir[202][202]; Cord cameFrom[202][202]; bool IsTFO(Cord c) { return (UTFO[c.x][c.y] == TFOkey); } void MakeTFO(Cord c) { UTFO[c.x][c.y] = TFOkey; } pair FindShortestPath(Cord beg, Cord tar, int carry) /// Finds the shortest path from beg to tar, carrying {carry} cakes. .first is the sequence, .second is the path length { //////////cout<<"Let's find the shortest path from "<(); memset(curdist, -1, sizeof(curdist)); curdist[beg.x][beg.y] = 0; UTFO[beg.x][beg.y] = TFOkey; for (int i=0; i nval)) { curdist[nx][ny] = nval; pq.push(GetQWE(nx, ny, nval)); cameFrom[nx][ny] = GetCord(top.x, top.y); } } } if (!good) return make_pair("-", -1); /// Could not find a match string build = ""; int curx, cury; curx = tar.x; cury = tar.y; do /// Iterating step by step backwards, starting from the last cell { int prevx = cameFrom[curx][cury].x, prevy = cameFrom[curx][cury].y; build += Direction(prevx, prevy, curx, cury); curx = prevx; cury = prevy; } while (curx != beg.x || cury != beg.y); reverse(build.begin(), build.end()); return make_pair(build, curdist[tar.x][tar.y]); } lld EvaluatePath(int x1, int y1, string path, int carry) { lld ret = 0; for (int i=0; i 0); reverse(ret.begin(), ret.end()); return ret; } int arrived = 0; pair GetOpt(int x1, int y1, int x2, int y2, int tbeg, int maxT, int realMT) /// .first is the path of the maximum, .second is the max number of cakes taken { string path = ""; int maxtake = -1; for (int i=1; i<=K; i++) { //continue; if (N>30 && N<100) {if (rand()&1) continue;} if (N>100) continue; if (!HaveTime()) break; int bl=0, br=100000, bmid, bres=-1, alltime=0; pair res1, res2; res1 = FindShortestPath(GetCord(x1, y1), sweets[i], 0); res2 = FindShortestPath(sweets[i], GetCord(x2, y2), 0); if (res1.second + res2.second > maxT) continue; while (bl<=br) { bmid = (bl+br)>>1; lld time = res1.second + EvaluatePath(sweets[i].x, sweets[i].y, res2.first, bmid); if (time > maxT) { br = bmid-1; continue; } else { bres = bmid; bl = bmid+1; alltime = time; } } if (maxtake < bres) { maxtake = bres; path = res1.first + ToString(maxtake) + res2.first; arrived = tbeg + alltime; } } if (maxtake == -1) { pair res; res = FindShortestPath(GetCord(x1, y1), GetCord(x2, y2), 0); if (res.second != -1 && res.second <= realMT) { arrived = tbeg + res.second; maxtake = 0; path = res.first; } } return make_pair(path, maxtake); } int dp[100002]; /// What is the maximum, after I attended party [i] string ans[100002]; pair EvaluateShuffle() { int curx, cury, curtime; curx = home.x; cury = home.y; curtime = 0; string ans = ""; int val = 0; for (int i=1; i<=P; i++) { if (!HaveTime()) break; if (parties[i].fin < curtime) continue; pair res = GetOpt(curx, cury, parties[i].x, parties[i].y, curtime, parties[i].beg-curtime, parties[i].fin-curtime); if (res.second == -1) continue; ans += res.first + "+"; if (res.second > 0) ans += ToString(res.second); arrived = max(arrived, parties[i].beg); val += (parties[i].fin-arrived) * (res.second+1); curx = parties[i].x; cury = parties[i].y; curtime = parties[i].fin; } return make_pair(val, ans); } int main () { srand(22335577); ios::sync_with_stdio(false); cin.tie(NULL); freopen("party.in", "r", stdin); freopen("party.out", "w", stdout); Input(); pair awesome; if (P <= 10000) { sort(parties+1, parties+P+1); awesome = EvaluateShuffle(); while (HaveTime()) { int f=rand()%P+1, t=rand()%(P-f+1)+f; random_shuffle(parties+f, parties+t+1); awesome = max(awesome, EvaluateShuffle()); sort(parties+f, parties+t+1); } } else { while (HaveTime()) { int f=rand()%P+1, t=rand()%(P-f+1)+f; random_shuffle(parties+f, parties+t+1); awesome = max(awesome, EvaluateShuffle()); sort(parties+f, parties+t+1); } } cout << awesome.second << "\n"; }