• Evanyou Blog 彩带


      题目传送门

    配对

    题目描述

    你有 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: 
    3
    3 65
    45 10
    60 25
    输出样例#1: 
    32
    输入样例#2: 
    3
    5 5
    6 7
    8 8
    输出样例#2: 
    5

    说明

    30%的数据满足:n <= 10^4

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


      分析:

      一开始打了个裸的贪心,然后30pts;然后看了five20巨佬写的正解,自己改,70pts;最后,开了long long,100pts。

      如果没有那个$a[i] eq b[i]$的要求,那么思路就很明显,直接贪心排序然后一一配对即可。

      然后我们在观察一下,发现$a[i],b[i]$都是唯一的,那么就在这个贪心的基础上改一下,把相同的元素试着与周围的元素交换。分析可以得到,只有相邻的3对元素互相交换才能保证最优解。有了这个思路就好办了,可以把它转换成DP,并且在做的时候我们都不用特判,当$a[i]=b[i]$时直接赋值为$inf$即可。

      Code:

    //It is made by HolseLee on 25th July 2018
    //Luogu.org P2507
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N=1e5+7;
    const int inf=1e9+7;
    ll n,a[N],b[N],dp[N],ans;
    
    inline ll minu(ll x,ll y)
    {
        return x==y?inf:(x>y?x-y:y-x);
    }
    
    inline ll Min(ll x,ll y)
    {
        return x>y?y:x;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<=n;i++)
        cin>>a[i]>>b[i];
        sort(a+1,a+n+1);
        sort(b+1,b+n+1);
        if(n==1&&a[1]==b[1]){
            cout<<"-1"<<"
    ";return 0;
        }
        dp[1]=minu(a[1],b[1]);
        dp[2]=Min(dp[1]+minu(a[2],b[2]),minu(a[1],b[2])+minu(a[2],b[1]));
        for(int i=3;i<=n;i++){
            dp[i]=dp[i-1]+minu(a[i],b[i]);
            dp[i]=Min(dp[i],dp[i-2]+minu(a[i],b[i-1])+minu(a[i-1],b[i]));
            dp[i]=Min(dp[i],dp[i-3]+minu(a[i],b[i-2])+minu(a[i-1],b[i])+minu(a[i-2],b[i-1]));
            dp[i]=Min(dp[i],dp[i-3]+minu(a[i],b[i-1])+minu(a[i-1],b[i-2])+minu(a[i-2],b[i]));
            dp[i]=Min(dp[i],dp[i-3]+minu(a[i],b[i-2])+minu(a[i-2],b[i])+minu(a[i-1],b[i-1]));
        }
        cout<<dp[n]<<"
    ";
        return 0;
    }
  • 相关阅读:
    Android设备管理器
    Android中读取手机联系人
    PopupWindow
    Activity之间数据的传递
    wpa_supplicant
    nandflash之基本特性
    NAND NOR Flash 和MTD
    mtd-util
    linux 常用命令
    minizip -基于zlib开源代码库
  • 原文地址:https://www.cnblogs.com/cytus/p/9368708.html
Copyright © 2020-2023  润新知