奇技淫巧训练之八
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;
}