3176 Cow Bowling


牛がボーリングするらしいよ…

問題文は謎だったけど、要するに2分木の根から葉までのスコアの最大値を求めるものらしい。

以前の俺ならすべてのパス(2^N個)のスコアを計算しようという愚行をしでかしていただろう。

だがッッ!!今の俺にはDPがいるッッッ!!

だからやってみた。


dp[i][j]をi列目の第jピンをパスに含めるときの、根からそのピンまでのスコアの最大値とする。

  • dp[1][1]はまぁ第1ピン。
  • dp[i][j](2<=i<=N, 1<=j<=i)はdp[i-1][j-1]とdp[i-1][j]の大きい方。

できたできた。scanfしたらそのままdp[i][j]を計算するという進歩!(以前なら一回ピンの配置を配列に確保してただろう)

ピンのスコアとして負の値が入ってくることを懸念してdpをINT_MINで初期化した版(47MS)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<climits>

using namespace std;

int main() {
    int N;
    scanf("%d", &N);
    int dp[N+2][N+2];
    for (int i = 0; i < N+2; ++i) {
        for (int j = 0; j < N+2; ++j) {
            dp[i][j] = INT_MIN;
        }
    }
    int ans = 0;
    scanf("%d", &dp[1][1]);
    for (int i = 2; i <= N; ++i) {
        for (int j = 1; j <= i; ++j) {
            int p;
            scanf("%d", &p);
            dp[i][j] = p + max(dp[i-1][j-1], dp[i-1][j]);
            if (i == N) ans = max(ans, dp[i][j]);
        }
    }
    printf("%d", ans);
}

みんなの見たらおろろが0MSだったから、dpを0で初期化してみた版(32MS)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<climits>

using namespace std;

int main() {
    int N;
    scanf("%d", &N);
    int dp[N+2][N+2];
    memset(dp, 0, sizeof(dp));
    int ans = 0;
    scanf("%d", &dp[1][1]);
    for (int i = 2; i <= N; ++i) {
        for (int j = 1; j <= i; ++j) {
            int p;
            scanf("%d", &p);
            dp[i][j] = p + max(dp[i-1][j-1], dp[i-1][j]);
            if (i == N) ans = max(ans, dp[i][j]);
        }
    }
    printf("%d", ans);
}

0MSの出し方plz><