Bzoj1237 [SCOI2008]配对

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1446  Solved: 551

Description

你有n 个整数Ai和n 个整数Bi。你需要把它们配对,即每个Ai恰好对应一 个Bp[i]。要求所有配对的整数差的绝对值之和尽量小,但不允许两个相同的数配 对。例如A={5,6,8},B={5,7,8},则最优配对方案是5配8, 6配5, 8配7,配对整数 的差的绝对值分别为2, 2, 1,和为5。注意,5配5,6配7,8配8是不允许的,因 为相同的数不许配对。

Input

第一行为一个正整数n,接下来是n 行,每行两个整数Ai和Bi,保证所有 Ai各不相同,Bi也各不相同。

Output

输出一个整数,即配对整数的差的绝对值之和的最小值。如果无法配对,输 出-1。

Sample Input

3
3 65
45 10
60 25

Sample Output

32

HINT

30%的数据满足:n <= 10^4 100%的数据满足:1 <= n <= 10^5,Ai和Bi均为1到106之间的整数。

Source

 

动态规划 线性DP 结论题

结论题,有趣。

如果没有匹配数不能相同的限制,分别将两数组排序,依次贪心匹配即可。

加上限制以后,匹配关系可能需要前后调整

由于a和b数组各自没有相同元素,可以脑洞出一个神奇的结论:调整的位置不会超过三位。

并不会证明。

于是直接推过去即可。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #define LL long long
 7 using namespace std;
 8 const int inf=1e9;
 9 const int mxn=100010;
10 int read(){
11     int x=0,f=1;char ch=getchar();
12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
14     return x*f;
15 }
16 inline int CP(int a,int b){return (a==b)?inf:abs(a-b);}
17 int n;
18 int a[mxn],b[mxn];
19 LL f[mxn];
20 int main(){
21 //    freopen("in.txt","r",stdin);
22     int i,j;
23     n=read();
24     for(i=1;i<=n;i++){
25         a[i]=read();b[i]=read();
26     }
27     sort(a+1,a+n+1);sort(b+1,b+n+1);
28     memset(f,0x3f,sizeof f);
29     f[0]=0;
30     f[1]=CP(a[1],b[1]);
31     f[2]=min(CP(a[1],b[1])+CP(a[2],b[2]),CP(a[1],b[2])+CP(a[2],b[1]));
32     for(i=3;i<=n;i++){
33         f[i]=min(f[i-1]+CP(a[i],b[i]),f[i-2]+CP(a[i-1],b[i])+CP(a[i],b[i-1]));
34         f[i]=min(f[i],f[i-3]+CP(a[i],b[i-1])+CP(a[i-1],b[i-2])+CP(a[i-2],b[i]));
35         f[i]=min(f[i],f[i-3]+CP(a[i],b[i-2])+CP(a[i-1],b[i-1])+CP(a[i-2],b[i]));
36         f[i]=min(f[i],f[i-3]+CP(a[i],b[i-2])+CP(a[i-1],b[i])+CP(a[i-2],b[i-1]));
37     }
38     if(f[n]>=0x3f3f3f3f3f3f3f)f[n]=-1;
39     printf("%lld\n",f[n]);
40     return 0;
41 }

 

转载于:https://www.cnblogs.com/SilverNebula/p/6925952.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值