Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Problem D. Daruma Otoshi / ダルマ落とし
- #include <bits/stdc++.h>
- using namespace std;
- auto solve(int n, const vector<int>& w) -> int {
- // 区間DP
- // dp[l][r] := (閉区間[l, r]における解)
- vector<vector<int>> dp(n, vector<int>(n, 0));
- // f(l, r) : l番目とr番目のブロックの重さの差が1以下なら2, それ以外なら0を返す
- auto f = [&w](int l, int r) {return abs(w[l] - w[r]) <= 1 ? 2 : 0;};
- // l番目からr番目の範囲で叩き出せるブロックの数の最大値
- // fm(l, r) : l+1番目からr-1番目のブロックがすべて叩き出されていていればl番目とr番目のブロックを叩き出す
- auto fm = [&](int l, int r) {return dp[l + 1][r - 1] + (dp[l + 1][r - 1] < r - l - 1 ? 0 : f(l, r));};
- // fl(l, r) : r-1番目とr番目のブロックを叩き出す
- auto fl = [&](int l, int r) {return dp[l][r - 2] + f(r - 1, r);};
- // fr(l, r) : l番目とr+1番目のブロックを叩き出す
- auto fr = [&](int l, int r) {return dp[l + 2][r] + f(l, l + 1);};
- // 区間長2のDPテーブルを埋める
- for(auto l = 0, r = l + 1; l < n - 1; l++, r++) dp[l][r] = f(l, r);
- // 短い区間から順にDPテーブルを更新
- for(auto len = 3; len < n; len += 2)
- for(auto l = 0, r = l + len; l < n - len; l++, r++)
- dp[l][r] = max({dp[l][r], fm(l, r), fl(l, r), fr(l, r)});
- // nが偶数ならdp[0][n - 1], 奇数ならdp[0][n - 2]かdp[1][n - 1]
- return max({dp[0][n - 1], dp[0][n - 2], dp[1][n - 1]});
- }
- auto main() -> int {
- int n;
- while(cin >> n, n) {
- vector<int> w(n);
- for(auto& i : w) cin >> i;
- cout << solve(n, w) << endl;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement