1 条题解

  • 0
    @ 2023-3-25 17:12:33

    原文求点赞qwq:https://www.luogu.com.cn/blog/560516/solution-p3080

    区间 dp。

    fi,j,0f_{i,j,0} 是捕捉了 [i,j][i,j] 的牛站在左端点的最少的已花费,fi,j,1f_{i,j,1} 是捕捉了 [i,j][i,j] 的牛站在右端点的最少的已花费。

    为什么一定是区间捕牛?因为这片区间是走过了,牛不捕白不捕

    转移方程如下:

    $$f_{i,j,0}=\min\{f_{i+1,j,0}+(d_{i+1}-d_{i})\times(c_{1,n}-c_{i+1,j}),f_{i+1,j,1}+(d_{j}-d_{i})\times(c_{i,n}-c_{i+1,j}) $$$$f_{i,j,1}=\min\{f_{i,j-1,0}+(d_{j}-d_{i})\times(c_{1,n}-c_{i,j-1}),f_{i,j-1,1}+(d_{j}-d_{j-1})\times(c_{i,n}-c_{i,j-1}) $$

    ci,jc_{i,j}[i,j][i,j] 的奶牛个数,也就是 ji+1j-i+1

    要排序。不然无序的不能区间 dp。

    然而,初始又在哪个端点呢?只要在端点中插入一个位置为 00 的端点,排序后二分即可。

    答案是 min{f1,n,0,f1,n,1}\min\{f_{1,n,0},f_{1,n,1}\}

    时间复杂度 O(n2)\mathcal{O}(n^2)

    代码实现如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 3005;
    int f[N][N][2], a[N], d[N], sum[N], n, c;
    int main() {
        cin >> n;
        for (int i = 1; i <= n; i ++)
            cin >> d[i];
        d[++ n] = 0, sort(d + 1, d + 1 + n);
        memset(f, 0x3f, sizeof f);
        c = lower_bound(d + 1, d + 1 + n, 0) - d;
        f[c][c][1] = f[c][c][0] = 0;
        for (int k = 2; k <= n; k ++)
            for (int i = 1; i <= n; i ++) {
                int j = i + k - 1;
                f[i][j][0] = min(f[i + 1][j][0] + (d[i + 1] - d[i]) * (i + n - j),
                                 f[i + 1][j][1] + (d[j] - d[i]) * (i + n - j));
                f[i][j][1] = min(f[i][j - 1][0] + (d[j] - d[i]) * (i + n - j),
                                 f[i][j - 1][1] + (d[j] - d[j - 1]) * (i + n - j));
            }
        cout << min(f[1][n][0], f[1][n][1]) << '\n';
        return 0;
    }
    
    
    • 1

    信息

    ID
    396
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    (无)
    递交数
    67
    已通过
    26
    上传者