1. 程式人生 > >[Luogu P2507] [BZOJ 1237] [SCOI2008]配對

[Luogu P2507] [BZOJ 1237] [SCOI2008]配對

洛谷傳送門

題目描述

你有 nn 個整數AiA_inn 個整數BiB_i。你需要把它們配對,即每個AiA_i恰好對應一個Bp[i]B_{p[i]}。要求所有配對的整數差的絕對值之和儘量小,但不允許兩個相同的數配對。例如A={5,6,8}A=\{5,6,8\}B={5,7,8}B=\{5,7,8\},則最優配對方案是5oˊ8,6oˊ5,8oˊ75ó8, 6ó5, 8ó7,配對整數的差的絕對值分別為2,2,12, 2, 1,和為55。注意,5oˊ56oˊ78oˊ85ó5,6ó7,8ó8

是不允許的,因為相同的數不許配對。

輸入輸出格式

輸入格式:

第一行為一個正整數nn,接下來是 nn 行,每行兩個整數AiA_iBiB_i,保證所有

AiA_i各不相同,BiB_i也各不相同。

輸出格式:

輸出一個整數,即配對整數的差的絕對值之和的最小值。如果無法配對,輸出1-1

輸入輸出樣例

輸入樣例#1:

3
3 65
45 10
60 25

輸出樣例#1:

32

輸入樣例#2:

3
5 5
6 7
8 8

輸出樣例#2:

5

說明

30%的資料滿足:n104n \le 10^4

100%的資料滿足:1n1051 \le n \le 10^5

AiA_iBiB_i均為1110610^6之間的整數。

解題分析

如果排序後兩兩對應不同, 顯然對應匹配最好。

當我們發現排序後a[i]=b[i]a[i]=b[i]的時候, 顯然我們只會考慮和其相鄰的兩個數交換匹配的情況(因為交換的越多越不優), 所以我們一遍dpdp考慮相鄰三個數就好。

程式碼如下:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <cmath> #define R register #define IN inline #define W while #define gc getchar() #define INF 100000000000ll #define MX 100050 #define ll long long template <class T> IN void in(T &x) { x = 0; R char c = gc; for (; !isdigit(c); c = gc); for (; isdigit(c); c = gc) x = (x << 1) + (x << 3) + c - 48; } using namespace std; IN ll judge(R int a, R int b) {return a == b ? INF : abs(a - b);} int n; ll dp[MX], a[MX], b[MX]; int main(void) { in(n); for (R int i = 1; i <= n; ++i) in(a[i]), in(b[i]); sort(a + 1, a + 1 + n), sort(b + 1, b + 1 + n); if(n == 1 && a[1] == b[1]) return puts("-1"), 0; dp[1] = judge(a[1], b[1]); dp[2] = min(dp[1] + judge(a[2], b[2]), judge(a[1], b[2]) + judge(a[2], b[1])); for (R int i = 3; i <= n; ++i) { dp[i] = dp[i - 1] + judge(a[i], b[i]); dp[i] = min(dp[i], dp[i - 2] + judge(a[i - 1], b[i]) + judge(a[i], b[i - 1])); dp[i] = min(dp[i], dp[i - 3] + judge(a[i - 1], b[i - 2]) + judge(a[i], b[i - 1]) + judge(a[i - 2], b[i])); dp[i] = min(dp[i], dp[i - 3] + judge(a[i], b[i - 2]) + judge(a[i - 2], b[i - 1]) + judge(a[i - 1], b[i])); dp[i] = min(dp[i], dp[i - 3] + judge(a[i], b[i - 2]) + judge(a[i - 1], b[i - 1]) + judge(a[i - 2], b[i])); } printf("%lld", dp[n]); }