题解【[SCOI2008] 配对】

题目链接

如果没有“配对数字不相同”的限制,将 a,b 数组排序后一 一配对就能得到最小值。

回到原题,考虑一种极端情况,i[1,n],ai=bi 即排序后全等。

n 为偶数,一种显然的构造方法是:

1 2 3 4 5 6
2 1 4 3 6 5

即分成两个两个一组,然后组内交换,这样跨越幅度最小,因此最终得出答案最小。

n 为奇数,两个一组显然不行,引入三个一组,比如 1 2 3 可对应 3 1 22 3 1,一定可以得到答案。

但是不需要引入四个一组,因为必然可以拆成“两个+两个”的模式。

回到原问题,设 fi 表示前 i 个元素的答案,那么转移有:

  • aibi 配对,fi1fi
  • ai,ai1bi,bi1fi2fi
  • ai,ai1,ai2bi,bi1,bi2fi3fi

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int n,a[N],b[N];
LL f[N];
LL calc(int p) {
vector<int> c;
LL minn=1e18;
c.push_back(b[p-2]); c.push_back(b[p-1]); c.push_back(b[p]);
do {
if(c[0]!=a[p]&&c[1]!=a[p-1]&&c[2]!=a[p-2]) {
minn=min(minn,abs(c[0]-a[p])*1ll+abs(c[1]-a[p-1])+abs(c[2]-a[p-2]));
}
} while(next_permutation(c.begin(),c.end()));
return minn;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
sort(a+1,a+1+n);
sort(b+1,b+1+n);
memset(f,0x3f,sizeof(f));
f[0]=0;
for(int i=1;i<=n;i++) {
if(i>=3)f[i]=calc(i)+f[i-3];
if(a[i]!=b[i]) f[i]=min(f[i],f[i-1]+abs(a[i]-b[i]));
if(i>=2&&(a[i]==b[i]||a[i-1]==b[i-1])) f[i]=min(f[i],f[i-2]+abs(a[i]-b[i-1])+abs(a[i-1]-b[i]));
}
cout<<f[n];
return 0;
}
posted @   2017BeiJiang  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示