トヨタプログラミングコンテスト2023#3 (AtCoder Beginner Contest 306) 6月17日 コンテスト第4問


その趣旨の話題

制限時間:2秒、容量制限:1024MB、スコア値:400点

問題の説明

シャオミンはレストランに来ました。料理は全部でN、最初の私料理には次の属性があります。

  • の場合X_{i}= 0、この料理は無毒で、食べればY_{i}美味しい価値が得られます。
  • の場合X_{i}= 1、この料理は毒ですが、食べるとY_{i}おいしい価値も得られます

当初、シャオミンの胃は健康でした。シャオミンが料理を食べるとき、彼は次のようにします。

  • 彼の胃が健康なとき
    • 料理に毒性がなければ、彼の胃はまだ健康です
    • その料理に毒が入っていたら、彼はお腹の虫になるでしょう
  • 彼がお腹の虫になったとき
    • 料理に毒性がなければ、彼の胃は健康になるでしょう
    • その料理に毒が入っていたら彼は死ぬだろう

1さて、最初の料理がシャオミンの前に1つずつ表示されます...最初のN料理が表示されるまで。それぞれの料理について、シャオミンは食べるか食べないかを選択できます。食べることを選択すると状態が変化しておいしさ値が増加(減少)しますが、食べないことを選択すると状態もおいしい値も変化しません。

さて、シャオミンには生きてレストランから出てきてもらいたいのですが、シャオミンが得られる最大のおいしい価値は何でしょうか?

データサイズ

  • 各値は整数です
  • 1\leq N\leq 3\times 10^{5}
  • X_{i}\in \left \{ 0,1\right \} (つまり、x_{i}0か1のどちらか)
  • -10^9 \leq Y_i \leq 10^9

入力

入力は次の形式の標準入力から取得されます。

N

X_1   Y_1

X_2   Y_2

X_N   Y_N

出力

答えを表す整数を出力します。


入力サンプル1

5
1 100
1 300
0 -200
1 500
1 300

出力サンプル1

600

説明例:

以下の選択肢により、Xiao Ming は死ぬことなく最大のおいしい値 (つまり 600) を得ることができます。

  •  彼は最初のコースをスキップすることを選択しました。今では彼の胃は健康で、おいしいポイントは合計 0 点です。
  •  彼は 2 番目のコースを楽しむことを選択しましたが、胃の調子が悪く、合計 300 おいしいポイントを獲得しました。
  •  彼は 3 番目のコースを楽しむことを選択しました。現在、彼の胃は健康で、合計 100 のおいしいポイントを獲得しています。
  •  彼は 4 番目のコースを楽しむことを選択しましたが、胃の調子が悪く、合計 600 おいしいポイントを獲得しました。
  •  彼は胃の調子が良くないため、5 番目のコースをスキップすることにしました。
  • 最終的に彼は600ポイントを獲得し、生きてレストランから出てきました。

入力サンプル2

4
0 -1
1 -2
0 -3
1 -4

出力サンプル2

0

この一連の例では、彼が取得できる最大の美味しさは 0 です。

入力サンプル3

15
1 900000000
0 600000000
1 -300000000
0 -700000000
1 200000000
1 300000000
0 -600000000
1 -900000000
1 600000000
1 -100000000
1 -400000000
0 900000000
0 200000000
1 -500000000
1 900000000

出力サンプル3

4100000000

答えは 32 ビット整数である必要はありません。


この質問は明らかに dp です。

dp[i][0] を定義すると、最初の i 品を食べても胃が元気で最大限の美味しさが得られることを意味し、dp[i][1] は最初の i 品を食べて胃の調子が悪くなることを意味します。料理の美味しさを最大限に価値を引き出します。それで:

dp[i][0] には 4 つのケースがあります: 0、dp[i-1][0]+y[i]、dp[i-1][1]+y[i] (前提: x[i] = =0)、dp[i-1][0]

dp[i][1] には 0、dp[i-1][0]+y (前提: x[i]==1)、dp[i-1][1] の 3 つのケースしかありません。

最終的に得られるおいしい最大値はmax(dp[n][0],dp[n][1])となります。

#include <iostream>
using namespace std;
typedef long long int ll;
ll n, dp[300005][2];
int main() {
	cin >> n;
	ll x, y;
	for (int i = 1; i <= n; i++) {
		cin >> x >> y;
		if (x == 0) {
			dp[i][0] = max(dp[i][0], max(dp[i - 1][0] + y, dp[i - 1][1] + y));
		}
		else {
			dp[i][1] = max(dp[i][1], dp[i - 1][0] + y);
		}
		dp[i][0] = max(dp[i][0], dp[i - 1][0]);
		dp[i][1] = max(dp[i][1], dp[i - 1][1]);
	}
	cout << max(dp[n][0], dp[n][1]) << endl;
	return 0;
}

もちろん、このコードは空間の複雑さを最適化することもできます。

#include <iostream>
using namespace std;
typedef long long int ll;
ll n;
int main() {
    cin >> n;
    ll p0 = 0, p1 = 0;
    ll x, y;
    for (int i = 1; i <= n; ++i) {
        cin >> x >> y;
        if (x == 0) {
            p0 = max(p0, max(p0 + y, p1 + y));
        }
        else {
            p1 = max(p1, p0 + y);
        }
    }
    cout << max(p1, p0) << endl;
}

簡単にできる!

おすすめ

転載: blog.csdn.net/qq_43546083/article/details/131320364