解题:SCOI 2008 配对

题面

如果没有两个数不能相同这个限制就两个数组排序后贪心即可。现在加上这个限制,注意到每个数组中的数是两两不同的,所以每次一定能在前面或后面一个数中找一个换过来,这样每次考虑相邻三个数转移就可以了,注意特判一下边界。

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=100005;
 7 long long a[N],b[N],dp[N],n,ans;
 8 inline long long diff(long long a,long long b)
 9 {
10     return (a==b)?1e12:abs(a-b);
11 }
12 inline long long mini(long long a,long long b)
13 {
14     return a<b?a:b;
15 }
16 int main ()
17 {
18     scanf("%lld",&n);
19     for(int i=1;i<=n;i++)
20         scanf("%lld%lld",&a[i],&b[i]);
21     sort(a+1,a+1+n),sort(b+1,b+1+n);
22     if(a[1]==b[1]&&n==1) {printf("-1"); return 0;}
23     memset(dp,0x3f,sizeof dp),dp[0]=0;
24     dp[1]=mini(dp[1],diff(a[1],b[1]));
25     dp[2]=mini(dp[2],dp[1]+diff(a[2],b[2]));
26     dp[2]=mini(dp[2],dp[0]+diff(a[1],b[2])+diff(a[2],b[1]));
27     for(int i=3;i<=n;i++)
28     {
29         dp[i]=mini(dp[i],dp[i-1]+diff(a[i],b[i]));
30         dp[i]=mini(dp[i],dp[i-2]+diff(a[i-1],b[i])+diff(a[i],b[i-1]));
31         dp[i]=mini(dp[i],dp[i-3]+diff(a[i-2],b[i])+diff(a[i-1],b[i-1])+diff(a[i],b[i-2]));
32         dp[i]=mini(dp[i],dp[i-3]+diff(a[i-2],b[i])+diff(a[i-1],b[i-2])+diff(a[i],b[i-1]));
33         dp[i]=mini(dp[i],dp[i-3]+diff(a[i-2],b[i-1])+diff(a[i-1],b[i])+diff(a[i],b[i-2]));
34      }
35      printf("%lld",dp[n]);
36     return 0;
37 } 
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9780180.html