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\n", dp[n]); return 0; } /* */