bzoj 1237: [SCOI2008]配对(贪心+DP)

题目描述

传送门

题目大意:给两组数,求一种匹配方案,使得每一位的数差的绝对值之和最小,要求同样的数不能匹配,输出最小的和。每组数各不相同,无法匹配输出-1。(n<=10^5)


题解

这一看就是一道我想不出来的题。话说我的DP简直太菜了,智商简直连个小学生都不如。

首先排序,如果没有限制对齐就行了,现在虽然有限制,但是其实交换距离最多不会超过2。如果超过2肯定可以换成2以内的交换使答案更优(自己举几个栗子)。我看了别人的题解才知道这个神奇的性质的。

然后就直接枚举怎样交换,随便DP一下就行了。

告诉你个秘密,要用long long。


代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#define maxn 100100
#define INF 1e15
#define LL long long

using namespace std;

int n;
int a[maxn], b[maxn];
LL f[maxn];

LL Calc(int x, int y){
    if(a[x] == b[y])  return INF;
    return (LL)abs(a[x] - b[y]);
}

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);

    for(int i = 1; i <= n; i++)  f[i] = INF;

    f[0] = 0LL;

    for(int i = 1; i <= n; i++){
        f[i] = f[i-1] + Calc(i, i);
        if(i >= 2)  f[i] = min(f[i], f[i-2] + Calc(i-1, i) + Calc(i, i-1));
        if(i >= 3)  f[i] = min(f[i], f[i-3] + Calc(i-2, i) + Calc(i-1, i-2) + Calc(i, i-1));
        if(i >= 3)  f[i] = min(f[i], f[i-3] + Calc(i-2, i-1) + Calc(i-1, i) + Calc(i, i-2));
    }

    if(f[n] == INF)  f[n] = -1;
    printf("%lld\n", f[n]);

    return 0;
}

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值