贪心+dp~观察数据,发现一个规律:将数字排序之后,最优匹配只可能产生在该数字和与它距离不超过二的数字之间。
所以可以用dp[i]代表前i个数(排序)匹配的最小差值,之后暴力选出该新数应该如何匹配。
以及题目保证A[i](B[i])中所有数字互不相同,这是为了避免一种情况的出现:
1 1 5 5
5 5 1 1
此时的最优解距离就超过了二啦。这种情况我并没有想到解,也很好奇是不是能够有接受这种情况的算法。
以下我丑丑的代码……(捂脸)、+INF要开大大大大大大大大大!
#include <bits/stdc++.h> using namespace std; #define maxn 2500000 #define INF 9999999999LL #define int long long int dp[maxn], a[maxn], b[maxn], n, mark[maxn], cnt[maxn]; int read() { int x = 0; char c; c = getchar(); while(c < '0' || c > '9') c = getchar(); while(c >='0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x; } int abs(int x, int y) { if(x == y) return INF; else return (x - y) >= 0 ? x - y : y - x; } signed main() { n = read(); for(int i = 1; i <= n; i ++) a[i] = read(), b[i] = read(); for(int i = 1; i <= n; i ++) dp[i] = INF; sort(a + 1, a + 1 + n); sort(b + 1, b + 1 + n); for(int i = 1; i <= n; i ++) { mark[i] += mark[i - 1]; if(a[i] == a[i - 1]) cnt[i] = cnt[i - 1] + 1; else cnt[i] = 1; if(a[i] == b[i]) mark[i] ++; if(a[i] != b[i]) dp[i] = dp[i - 1] + abs(a[i], b[i]); if(i >= 2) { if(a[i] != a[i - 1]) dp[i] = min(dp[i - 2] + abs(a[i], b[i - 1]) + abs(b[i], a[i - 1]), dp[i]); if(i >= 3 && mark[i] - mark[i - 3] >= 2) { int tem = abs(a[i], b[i - 2]) + abs(a[i - 1], b[i]) + abs(a[i - 2], b[i - 1]); tem = min(tem, abs(a[i], b[i - 1]) + abs(a[i - 1], b[i - 2]) + abs(a[i - 2], b[i])); tem = min(tem, abs(a[i], b[i - 2]) + abs(a[i - 1], b[i - 1]) + abs(a[i - 2], b[i])); dp[i] = min(dp[i], dp[i - 3] + tem); } } } if(dp[n] >= INF) printf("-1 "); else printf("%lld ", dp[n]); return 0; }