奇技淫巧训练之八

https://www.luogu.org/problem/P2507

分析:

首先看到这道题一定不会是什么高级算法,肯定是贪心啊dp啊

先考虑ai可以等于bi,则直接排序即可

但是ai!=bi的,怎么办?

读题!!!

上帝给你关了一道门一定会再给你开一扇窗de

a数组和b数组内部元素是不等的

  • 所以需要交换
  • 此时交换的范围越小,绝对值和越小

我们贪心的想到,因为每个数顶多在a,b中各出现一次

所以当某次ai=bi时,则ai!=b(i-1),ai!=b(i+1)

因为是绝对值,你不知道ai-b(i-1)和b(i+1)-ai谁更大

所以要取个最小

  • a1-b1
  • a1-b2,a2-b1(两两交换)
  • a1-b2,a2-b3,a3-b1(3个之间的交换)
  • a1-b3,a2-b1,a3-b2(3个之间的交换)

这时你会想问

这样不会重复吗?

考虑吧a(i-1),ai,a(i+1)变为ai,a(i+1),a(i+2),于是就线性推过去dp,是不会重复的

如果还是不清楚的话,见代码就会明白了

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=100005;
const long long M=1e13;
int a[N],b[N],n;
long long f[N],ans;

long long Min(long long a,long long b)
{
if (a<b) return a;
return b;
}
long long js(int l,int r)
{
if (a[l]==b[r]) return M;
return abs(a[l]-b[r]);
}
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);
if (n==1&&a[1]==b[1]) printf("-1\n");
else
{
    f[0]=0;
    for (int i=1; i<=n; i++)
    {
        ans=M;
        if (i>=1) ans=Min(ans,f[i-1]+js(i,i)); 
        if (i>=2) ans=Min(ans,f[i-2]+js(i-1,i)+js(i,i-1));
        if (i>=3) 
        {
            ans=Min(ans,f[i-3]+js(i-2,i-1)+js(i-1,i)+js(i,i-2));
            ans=Min(ans,f[i-3]+js(i-2,i)+js(i-1,i-2)+js(i,i-1));
        } 
        f[i]=ans;
    }
    printf("%lld\n",f[n]);
}
return 0;
}
posted @ 2019-10-17 08:54  wzx_believer  阅读(84)  评论(0编辑  收藏  举报