DestinHistoire

 

BZOJ-1237 [SCOI2008]配对(dp)

题目描述

  给一个长为 \(n\) 的序列 \(a=[a_1,a_2,\cdots,a_n]\) 和一个长为 \(n\) 的序列 \(b=[b_1,b_2,\cdots,b_n]\)(保证所有 \(a_i\) 互不相同,所有 \(b_i\) 互不相同),把它们配对,即每个 \(a_i\) 对应一个 \(b_i\),要求所有配对的整数差的绝对值之和尽量小,但不允许两个相同的数配对。如果无法配对,输出 \(-1\)

  数据范围:\(1\leq n\leq 10^5,1\leq a_i,b_i\leq 10^6\)

分析

  假设不考虑不允许相同的数配对的限制,则把两个序列排序后对应项一一匹配就是最优答案。

  现在考虑限制条件,且只考虑前 \(i\) 对数,由于保证 $a_i $ 互不相同, \(b_i\) 互不相同,所以排序后如果有 \(a_i=b_i\),则一定有 \(a_i\neq b_{i-1},a_{i}\neq b_{i-2},b_i\neq a_{i-1},b_i\neq a_{i-2}\)。有如下匹配方案:

  \(0.\) \(a_{i}\) 匹配 \(b_{i}\)\(a_i\neq b_i\))。

  $ 1.$ \(a_{i-1}\) 匹配 \(b_i\)\(a_i\) 匹配 \(b_{i-1}\)

  $ 2.$ \(a_{i}\) 匹配 \(b_{i-2}\)\(a_{i-1}\) 匹配 \(b_{i-1}\)\(a_{i-2}\) 匹配 \(b_{i}\)

  $ 3.$ $a_{i} $ 匹配 \(b_{i-1}\),$a_{i-1} $ 匹配 $b_{i-2} \(,\)a_{i-2} $ 匹配 \(b_i\)

  \(4.\) \(a_i\) 匹配 \(b_{i-2}\)\(a_{i-1}\) 匹配 \(b_i\)\(a_{i-2}\) 匹配 \(b_{i-1}\)

  因此可以归纳出一个结论:每个数 \(a\) 与其匹配的数 \(b\) 下标之差不会超过 \(2\)

  设 \(dp[i]\) 表示前 \(i\) 对数配对能得到的最小值。\(dp[1]=|a_1-b_1|,dp[2]=\min(dp[1]+|a_2-b_2|,|a_1-b_2|+|a_2-b_1|)\)(如果 \(n=1\)\(a_1=b_1\) 将其特判掉)。

  接下来考虑状态转移方程:

  方案 \(0\)\(dp[i]=dp[i-1]+|a_i-b_i|\)

  方案 \(1\)\(dp[i]=\min(dp[i],dp[i-2]+|a_i-b_{i-1}|+|a_{i-1}-b_i|)\)

  方案 \(2\):$dp[i]=\min(dp[i],dp[i-3]+|a_i-b_{i-2}|+|a_{i-1}-b_{i-1}|+|a_{i-2}-b_i|) $。

  方案 \(3\)\(dp[i]=\min(dp[i],dp[i-3]+|a_i-b_{i-1}|+|a_{i-1}-b_{i-2}|+|a_{i-2}-b_i|)\)

  方案 \(4\)\(dp[i]=\min(dp[i],dp[i-3]+|a_{i}-b_{i-2}|+|a_{i-1}-b_{i}|+|a_{i-2}-b_{i-1}|)\)

  \(dp[n]\) 即为答案,时间复杂度 \(O(n)\)

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const long long INF=1e18;
long long n,dp[N],a[N],b[N];
long long ABS(long long a,long long b)
{
    if(a==b)
        return INF;
    return abs(a-b);
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%d %d",&a[i],&b[i]);
    sort(a+1,a+1+n);
    sort(b+1,b+1+n);
    if(n==1&&a[1]==b[1])
    {
        puts("-1");
        return 0;
    }
    dp[1]=ABS(a[1],b[1]);
    dp[2]=min(dp[1]+ABS(a[2],b[2]),ABS(a[1],b[2])+ABS(a[2],b[1]));
    for(int i=3;i<=n;i++)
    {
        dp[i]=dp[i-1]+ABS(a[i],b[i]);
        dp[i]=min(dp[i],dp[i-2]+ABS(a[i],b[i-1])+ABS(a[i-1],b[i]));
        dp[i]=min(dp[i],dp[i-3]+ABS(a[i],b[i-2])+ABS(a[i-1],b[i-1])+ABS(a[i-2],b[i]));
        dp[i]=min(dp[i],dp[i-3]+ABS(a[i],b[i-1])+ABS(a[i-1],b[i-2])+ABS(a[i-2],b[i]));
        dp[i]=min(dp[i],dp[i-3]+ABS(a[i],b[i-2])+ABS(a[i-1],b[i])+ABS(a[i-2],b[i-1]));
    }
    cout<<dp[n]<<endl;
    return 0;
}

posted on 2020-12-13 15:07  DestinHistoire  阅读(51)  评论(0编辑  收藏  举报

导航