[SCOI2008]配对 解题报告

[SCOI2008]配对

题意

\(n\) 个整数 \(a_i,b_i\) (\(a_i\) 各不相同, \(b_i\) 也各不相同),
\((1\le n\le 10^5,\ 1\le a_i,b_i \le 10^6)\), 将 \(a_i,b_j\) 两两配对, 要求相同的两个数不能配对, 使得每一对数的差的绝对值之和最小, 输出这个最小值.

思路

首先, 把 \(a,b\) 从小到大排序, 若果没有 "相同的两个数不能配对" 这个条件, 那么把每一对 \(a_i,b_i\) 配对一定是最优的.

因为 \(a,b\) 中的数各不相同, 所以对于相等的 \(a_i,\ b_i\), 可以在 3 组数以内把它消化完,
若把它与更远的数进行配对, 肯定是不优的,

所以, 我们可以枚举三组 \(a_i,b_i\) 两两配对的所有方式, 然后取最小值就行了.

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+7;
const ll inf=1e17;
int n;
ll a[N],b[N],f[N];
int main(){
//  freopen("match.in","r",stdin);
    cin>>n; for(int i=1;i<=n;i++) scanf("%lld%lld",&a[i],&b[i]);
    sort(a+1,a+1+n); sort(b+1,b+1+n);
    if(a[1]==b[1]) f[1]=inf;
    else f[1]=abs(a[1]-b[1]);
    if(a[1]==b[1]||a[2]==b[2]) f[2]=abs(a[2]-b[1])+abs(a[1]-b[2]);
    else f[2]=abs(a[2]-b[2])+abs(a[1]-b[1]);
    for(int i=3;i<=n;i++){
        ll t1=inf,t2=inf,t3=inf,t4=inf,t5=inf;;
        if(a[i]!=b[i]) t1=f[i-1]+abs(a[i]-b[i]);
        if(a[i]!=b[i-1]){
            if(a[i-1]!=b[i]) t2=f[i-2]+abs(a[i]-b[i-1])+abs(a[i-1]-b[i]);
            if(a[i-1]!=b[i-2]&&a[i-2]!=b[i]) t3=f[i-3]+abs(a[i]-b[i-1])+abs(a[i-1]-b[i-2])+abs(a[i-2]-b[i]);
        }
        if(a[i]!=b[i-2]){
            if(a[i-1]!=b[i]&&a[i-2]!=b[i-1]) t4=f[i-3]+abs(a[i]-b[i-2])+abs(a[i-1]-b[i])+abs(a[i-2]-b[i-1]);
            if(a[i-1]!=b[i-1]&&a[i-2]!=b[i]) t5=f[i-3]+abs(a[i]-b[i-2])+abs(a[i-1]-b[i-1])+abs(a[i-2]-b[i]);
        }
        f[i]=min(min(t1,min(t2,t3)),min(t4,t5));
    }
    printf("%lld\n",f[n]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/brucew-07/p/11807482.html