2023牛客暑期多校训练营2

K - Box

https://ac.nowcoder.com/acm/contest/57356/K

题意

给出一个长度为 n01 串以及每个位置都有权值 ai0 ,每个 1 最多移动一次且最多移动一位。若一个位置有 1 则可以获得权值,问最大可能的权值和。

n106

题解

状态表示:

ai:= 权重数组

bi:= 01 数组

dpij:= 考虑数列 1i 位,j=0 代表此处的 1 挪到上一位,j=1 代表此处的 1 不动,j=2 代表此处的 1 挪到下一位,此时的最大权值和为 dpij.

状态计算:

  • bi=0

    • dpi,0=dpi1,0
    • dpi,1=dpi1,1
    • dpi,2=dpi1,2
  • bi=1

    • 如果与上一个 1 的距离为 1:初始状态为 11(下面的箭头代表 1 的初始位置)

      • dpi,0=dpi1,0+ai1:代表情况为 11 ^0 ^0
      • dpi,1=max{dpi1,0,dpi1,1}+ai:代表情况为 max{10 ^1 ^0,01 ^1 ^0}
      • dpi,2=max{dpi1,0,dpi1,1,dpi1,2}+ai+1:代表情况为 max{10 ^0 ^1,01 ^0 ^1,00 ^1 ^1}
    • 如果与上一个 1 的距离为 2:初始状态为 101

      • dpi,0=max{dpi1,0,dpi1,1}+ai1:代表情况为 max{10 ^10 ^0,01 ^10 ^0}
      • dpi,1=max{dpi1,0,dpi1,1,dpi1,2}+ai:代表情况为 max{10 ^01 ^0,01 ^01 ^0,00 ^11 ^0}
      • dpi,2=max{dpi1,0,dpi1,1,dpi1,2}+ai+1:代表情况为 max{10 ^00 ^1,01 ^00 ^1,00 ^10 ^1}
    • 如果与上一个 1 的距离为 3:初始状态为 1001

      • dpi,0=max{dpi1,0,dpi1,1,dpi1,2}+ai1:代表情况为 max{10 ^010 ^0,01 ^010 ^0,00 ^110 ^0}
      • dpi,1=max{dpi1,0,dpi1,1,dpi1,2}+ai:代表情况为 max{10 ^001 ^0,01 ^001 ^0,00 ^101 ^0}
      • dpi,2=max{dpi1,0,dpi1,1,dpi1,2}+ai+1:代表情况为 max{10 ^000 ^1,01 ^000 ^1,00 ^100 ^1}

代码

#include <bits/stdc++.h>
#define endl '\n'
#define int long long

using namespace std;

void solve()
{
    int n;
    cin >> n;
    vector<int> a(n + 10), b(n + 10);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
        cin >> b[i];
    vector<vector<int>> dp(n + 10, vector<int>(3));
    int last = -2;
    for (int i = 1; i <= n; i++)
    {
        if (b[i] == 1)
        {
            if (i - last == 1)
            {
                dp[i][0] = dp[i - 1][0] + a[i - 1];
                dp[i][1] = max({dp[i - 1][0], dp[i - 1][1]}) + a[i];
                dp[i][2] = max({dp[i - 1][0], dp[i - 1][1], dp[i - 1][2]}) + a[i + 1];
            }
            else if (i - last == 2)
            {
                dp[i][0] = max({dp[i - 1][0], dp[i - 1][1]}) + a[i - 1];
                dp[i][1] = max({dp[i - 1][0], dp[i - 1][1], dp[i - 1][2]}) + a[i];
                dp[i][2] = max({dp[i - 1][0], dp[i - 1][1], dp[i - 1][2]}) + a[i + 1];
            }
            else
            {
                dp[i][0] = max({dp[i - 1][0], dp[i - 1][1], dp[i - 1][2]}) + a[i - 1];
                dp[i][1] = max({dp[i - 1][0], dp[i - 1][1], dp[i - 1][2]}) + a[i];
                dp[i][2] = max({dp[i - 1][0], dp[i - 1][1], dp[i - 1][2]}) + a[i + 1];
            }
            last = i;
        }
        else
        {
            dp[i][0] = dp[i - 1][0];
            dp[i][1] = dp[i - 1][1];
            dp[i][2] = dp[i - 1][2];
        }
    }
    cout << max({dp[n][0], dp[n][1], dp[n][2]}) << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}