PKU 1042 Gone Fishing
問題
n個の湖でhの制限時間内で釣りをする。
最初、1番の湖から出発する。
i番目の湖からはi+1番目の湖に行くか、その湖で釣りを終了するかしかできない。
i番目の湖からi+1番目の湖へはt[i]の時間がかかる。
i番目の湖では最初の1単位時間ではf[i]の魚が取れるが、
次の単位時間からはd[i]ずつ取れる魚が減っていく。(マイナスになることはない)
最も魚の取れる取り方を出力せよ。
そのような取り方が複数ある場合、1番目の湖で釣りをする時間を最大に、
それでも複数ある場合2番目の湖で釣りをする時間を最大に……というようにするものとする。
制約条件
n≦25
h≦200くらい
ソースコード
int n, h, f[30], d[30], T[30]; int dp[30][300], ans[30], next[30][300]; int rec(int c, int t){ int &res = dp[c][t]; if(res >= 0) return res; res = 0; int fish = 0, mxi = -1; bool finish = 0; for(int i = 0; i <= t; i++){ if(c < n - 1 && t - i >= T[c]){ int tmp = rec(c + 1, t - i - T[c]) + fish; if(res <= tmp) res = tmp, mxi = i, finish = 0; } int tmp = fish; if(res <= tmp) res = tmp, mxi = i, finish = 1; fish += max(0, f[c] - i * d[c]); } next[c][t] = finish ? -1 : mxi; return res; } int main(){ int cs = 0; while(cin >> n, n){ if(cs++) cout << endl; cin >> h; rep(i, n) cin >> f[i]; rep(i, n) cin >> d[i]; rep(i, n - 1) cin >> T[i]; memset(ans, 0, sizeof(ans)); memset(dp, -1, sizeof(dp)); rec(0, h * 12); int t = h * 12; rep(i, n){ if(next[i][t] < 0){ ans[i] = t * 5; break; } ans[i] = next[i][t] * 5; t -= next[i][t] + T[i]; } rep(i, n) cout << ans[i] << (i == n - 1 ? "\n" : ", "); printf("Number of fish expected: %d\n", dp[0][h * 12]); } return 0; }