[CF321E] Ciel and Gondolas

[CF321E] Ciel and Gondolas - 决策单调性dp

Description

有 n 个人在队列里,有 k 条船,第 i 条船到时,前若干个人可以上船。最后一条船将载走所有的人。第 i 个人和第 j 个人处在同一条船上会产生 uij 的沮丧值,求出最小的沮丧值和。(n le 4000, k le 800)

Solution

O(nnk) 的 dp 是显然的,由于满足四边形不等式,具有决策单调性

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 4005;

int n, m, f[N][N], s[N][N], p[N][N];

inline int read()
{
    int x = 0;
    bool t = false;
    char ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-')
        ch = getchar();
    if (ch == '-')
        t = true, ch = getchar();
    while (ch <= '9' && ch >= '0')
        x = x * 10 + ch - 48, ch = getchar();
    return t ? -x : x;
}

signed main()
{
    n = read();
    m = read();
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            s[i][j] = read();
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
    memset(f, 0x3f, sizeof f);
    for (int i = 0; i <= m; i++)
        f[0][i] = 0, p[n + 1][i] = n - 1;
    for (int j = 1; j <= m; j++)
        for (int i = n; i >= 1; i--)
            for (int k = p[i][j - 1]; k <= p[i + 1][j]; k++)
            {
                int tmp = f[k][j - 1] + (s[i][i] + s[k][k] - s[i][k] - s[k][i]) / 2;
                if (tmp <= f[i][j])
                    f[i][j] = tmp, p[i][j] = k;
            }
    cout << f[n][m] << endl;
}
原文地址:https://www.cnblogs.com/mollnn/p/14361110.html