GCJ 2010 Qualification Round C.Theme Park
問題
http://code.google.com/codejam/contest/dashboard?c=433101#s=p2
- それぞれ、g_0, ..., g_{n - 1} 人から成る n 個のグループが遊園地のジェットコースターに乗る。
- ジェットコースターには k 人同時に乗れる。
- ジェットコースターは1日に r 回走る。
- ジェットコースターには、列の先頭に居るグループから、順番に、k 人を超えない範囲で出来るだけたくさんが搭乗する。
- この時、列の n 番目のグループが乗れないなら、n + 1 番目以降も、その回には乗らない。
- ジェットコースターに乗ったグループは、列の最後に並ぶ。
- この遊園地の営業時間は超長い or ジェットコースターが超スピーディー。1日で、最大 ジェットコースターは 10^8 回くらい走る。
- さらに、このジェットコースターも超長い。最大で、10^9 人乗れる。
方針
- 単純には、遊園地の営業開始から、シミュレーションすれば良いけど、時間が足りない。
- グループ数の最大値は小さいので、各グループ i に対して、列の先頭が グループ i だった時、その回に何人が乗れるか、次の回の先頭グループはどこか, を予め計算しておく。
答案
/*! if g++ -Wall -g ThemePark.cpp; then ./a.out < test.in; fi */ #include <iostream> #include <vector> #include <string> #include <iterator> using namespace std; typedef unsigned long long ull; void makeMemo(vector<ull>& nextTop, vector<ull>& revenue, vector<ull>& g, ull n, ull k){ nextTop.resize(n); revenue.resize(n); for(ull i = 0; i < n; i++){ ull j; revenue[i] = 0; for(j = 0; j < n; j++){ if(revenue[i] + g[(i + j) % n] > k) break; revenue[i] += g[(i + j) % n]; } nextTop[i] = (i + j) % n; } } void solve(ull r, ull k, ull n, vector<ull>& g, int caseNum){ vector<ull> nextTop, revenue; makeMemo(nextTop, revenue, g, n, k); ull ret = 0; ull next = 0; for(ull i = 0; i < r; i++){ ret += revenue[next]; next = nextTop[next]; } cout << "Case #" << (caseNum + 1) << ": " << ret << endl; } int main(int argc, char* argv[]){ int t; cin >> t; for(int i = 0; i < t; i++){ ull r, k, n; cin >> r >> k >> n; vector<ull> g(n); for(ull j = 0; j < n; j++){ cin >> g[j]; } solve(r, k, n, g, i); } return 0; }