《算法进阶指南》环形结构上的DP问题 休息时间

这题由于前一个小时会对后一个小时造成影响,所以必须考虑0时是否连续问题。可以在dp时分别令0时为连续与不连续,目标状态就取第n时休息的状态和不休息的状态。
这题必须开滚动数组,否则空间会爆。


using namespace std;
// #define int long long
#define INF 1e18
#define endl '\n'

int n, b;
int arr[4003];

int f[2][3833][2] = {0};
void init()
{
}
void solve()
{
    memset(f, -0x3f, sizeof(f));
    cin >> n >> b;
    f[1][0][0] = 0;
    f[1][1][1] = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> arr[i];
    }
    for (int i = 2; i <= n; i++)
    {
        for (int j = 0; j <= b; j++)
        {
            int nowi = i & 1;
            f[nowi][j][0] = max({f[nowi ^ 1][j][1], f[nowi ^ 1][j][0]});
            if (j >= 1)
            {
                f[nowi][j][1] = max({f[nowi ^ 1][j - 1][0], f[nowi ^ 1][j - 1][1] + arr[i]});
            }
        }
    }
    int ans1 = max(f[n & 1][b][0], f[n & 1][b][1]);
    memset(f, -0x3f, sizeof(f));
    f[1][0][0] = 0;
    f[1][1][1] = arr[1];
    for (int i = 2; i <= n; i++)
    {
        for (int j = 0; j <= b; j++)
        {
            int nowi = i & 1;
            f[nowi][j][0] = max({f[nowi ^ 1][j][1], f[nowi ^ 1][j][0]});
            if (j >= 1)
            {
                f[nowi][j][1] = max({f[nowi ^ 1][j - 1][0], f[nowi ^ 1][j - 1][1] + arr[i]});
            }
        }
    }
    int ans2 = f[n & 1][b][1];
    cout << max(ans1, ans2) << endl;
}

signed main()
{
#ifdef LOCAL_ENV
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false), cin.tie(0);
    int T = 1;
    // cin >> T;

    for (int i = 1; i <= T; i++)
    {
        solve();
    }
    return 0;
}

收获:
1.环形问题不仅有破环成链一个思路,还可以处理环形边界,令环形边界为连续和不连续两种状态,并分别计算。

posted @ 2025-03-19 22:02  青一凡  阅读(11)  评论(0)    收藏  举报