[SCOI2008]配对

 [SCOI2008]配对
题目背景
四川NOI2008省选
题目描述
你有 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是不允许的,因为相同的数不许配对。
输入输出格式
输入格式:
第一行为一个正整数n,接下来是n 行,每行两个整数Ai和Bi,保证所有
Ai各不相同,Bi也各不相同。
输出格式:
输出一个整数,即配对整数的差的绝对值之和的最小值。如果无法配对,输
出-1。
输入输出样例
输入样例#1:
33 6545 1060 25
输出样例#1:
32
输入样例#2:
35 56 78 8
输出样例#2:
5
说明
30%的数据满足:n <= 10^4
100%的数据满足:1 <= n <= 10^5,Ai和Bi均为1到10^6之间的整数。

题解:
如果没有整数不能匹配的要求,那么答案就是排序后一一对应的答案。
而如果连着两个数相等的话可以与旁边的数进行交换后匹配。
对于连着三个数相等的情况的话有两种交换方法:

分类讨论后转移即可。

代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;

const int max_n = 1e5+7;
const LL  inf   = 1e15+7;

int a[max_n],b[max_n];
LL f[max_n];
int n,ans; 

inline LL num(int x,int y)
{
	if(a[x]==b[y])  return inf;
	else return abs(a[x]-b[y]);
}

inline void dp()
{
	for(int i=1; i<=n; ++i)
	  f[i]=inf;
	f[0]=0;
	for(int i=1; i<=n; ++i)
	{
		if(i>=1) f[i]=min(f[i],f[i-1]+num(i,i));
		if(i>=2) f[i]=min(f[i],f[i-2]+num(i-1,i)+num(i,i-1));
		if(i>=3) f[i]=min(f[i],min(f[i-3]+num(i-2,i)+num(i-1,i-2)+num(i,i-1),f[i-3]+num(i-2,i-1)+num(i-1,i)+num(i,i-2)));
	}  
}

int main()
{
	scanf("%d",&n);
	for(int i=1; i<=n; ++i)
	  scanf("%d%d",&a[i],&b[i]);
	sort(a+1,a+n+1);
	sort(b+1,b+n+1);
	dp();
	printf("%lld\n",f[n]);
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值