题解:P7987 [USACO21DEC] Paired Up G

· · 题解

考虑定义 f(i,0/1) 表示前 i 个数,没选的数的个数的奇偶性是 0/1 的方案数。

解释一下定义,显然我们要讨论当前考虑的奶牛是跟前面一个配对还是后面的配对,而这样定义可以简化转移,当然你也可以设前 i 个数选的数的奇偶性。于是就有了第二维。

考虑转移:

有了这些结论,推转移方程就不难了。

code:

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

const int N = 1e5 + 10;
int t, n, k, x[N], y[N], f[N][2];

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> t >> n >> k;
    if (t == 2) t = -1;
    for (int i = 1; i <= n; ++i) cin >> x[i] >> y[i], y[i] *= t;
    x[0] = -2e9, x[n + 1] = 2e9;
    memset(f, 63, sizeof f);
    f[0][0] = 0;
    for (int i = 1, lst = 0; i <= n; ++i) {
        while (x[i] - x[lst + 1] > k) ++lst;
        int id = i & 1;
        if (x[i] - x[i - 1] <= k) f[i][id] = min(f[i][id], f[i - 1][id]);
        if (x[i + 1] - x[i] <= k) f[i][id ^ 1] = min(f[i][id ^ 1], f[i - 1][id ^ 1]);
        f[i][id] = min(f[i][id], f[lst][id ^ 1] + y[i]);
        if (x[i + 1] - x[i - 1] <= k) f[i][id ^ 1] = min(f[i][id ^ 1], f[lst][id] + y[i]);
    }
    cout << abs(f[n][n & 1]);
    return 0;
}

后记:做题一定要看数据范围,注意到这个 dp 成立的条件是 K>0,可以自己想想为什么。