mayoko’s diary

プロコンとかいろいろ。

CODE FESTIVAL 2014 Hard B - ぽよぽよ

ぽよ〜

解法

dp で解けます。

dp[n][x] = (n 番目の人が, もとの位置から x 以下だけずれた座標にいるような場合の数)
とすると, n 番目の人は, p[n]+x-1 以下の座標にいるか, p[n]+x の座標にいるかのどちらかです。前者は dp[n][x-1] でわかりますね。後者は, n-1 番目の人が p[n]+x-1 以下の座標にいれば良いです。このような場合の数は, dp[n-1][y] で求めることができるので, 上手いことやりましょう。

const int MAXN = 1022;
const ll MOD = 1e9+7;
ll p[MAXN], l[MAXN];
ll dp[MAXN][2*MAXN];

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    p[0] = -1ll<<50;
    for (int i = 1; i <= n; i++) cin >> p[i] >> l[i];
    for (int i = MAXN; i < 2*MAXN; i++) dp[0][i] = 1;
    for (int i = 1; i <= n; i++) {
        for (ll x = -l[i]; x <= l[i]; x++) {
            ll y = p[i] - p[i-1] + x - 1;
            dp[i][x+MAXN] = dp[i][x+MAXN-1];
            y = min<ll>(y, 1000);
            y = max<ll>(y, -1001);
            if (y > -1001) {
                (dp[i][x+MAXN] += dp[i-1][MAXN+y]) %= MOD;
            }
        }
        for (ll x = MAXN+l[i]+1; x < 2*MAXN; x++) dp[i][x] = dp[i][x-1];
    }
    cout << dp[n][2*MAXN-1] << endl;
    return 0;
}