bzoj 1237 [SCOI2008]配对 贪心+dp

思路:dp[ i ] 表示 排序后前 i 个元素匹配的最小值, 我们可以发现每个点和它匹配的点的距离不会超过2,这样就能转移啦。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int,int>
#define piii pair<int, pair<int,int> >

using namespace std;

const int N = 1e5 + 7;
const int M = 10 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

int n;
LL a[N], b[N], dp[N];
LL cal(LL x) {
    return x == 0 ? 10000000000000ll : abs(x);
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lld%lld", &a[i], &b[i]);

    sort(a + 1, a + 1 + n);
    sort(b + 1, b + 1 + n);

    dp[1] = cal(a[1] - b[1]);
    dp[2] = dp[1] + cal(a[2] - b[2]);
    dp[2] = min(dp[2], cal(a[2] - b[1]) + cal(a[1] - b[2]));
    for(int i = 3; i <= n; i++) {
        dp[i] = dp[i - 1] + cal(a[i] - b[i]);
        dp[i] = min(dp[i], dp[i - 2] + cal(a[i - 1] - b[i]) + cal(a[i] - b[i - 1]));
        dp[i] = min(dp[i], dp[i - 3] + cal(a[i] - b[i - 2]) + cal(a[i - 2] - b[i - 1]) + cal(a[i - 1] - b[i]));
        dp[i] = min(dp[i], dp[i - 3] + cal(a[i - 2] - b[i]) + cal(a[i - 1] - b[i - 2]) + cal(a[i] - b[i - 1]));
    }

    if(dp[n] >= 10000000000000ll) puts("-1");
    else printf("%lld
", dp[n]);
    return 0;
}
/*
*/
原文地址:https://www.cnblogs.com/CJLHY/p/9127670.html