B1237 [SCOI2008]配对 贪心 + dp

我刚开始,我打眼一看:哇!网络流大水题,直接费用流板子,建边跟zz一样。结果看了一眼数据范围。。。gg,luogu上只能得30,直接建边就是n^2,1e5根本过不了。咋办,只能另谋出路。想不出来,看题解之后恍然大悟!!!woc,还有这样一句话:

保证所有 Ai各不相同,Bi也各不相同。

惊了,但是还是不会,然后就有这样一个显而易见的东西:a[i]只能和b[i - 1],b[i],b[i + 1]匹配,否则一定不是最优解。。。然后和dp一样的思路,每个状态由4个枚举转移过来,然后就好了。

然后20???分怎么还少了???然后尝试开longlong,30。。。后来发现中间有一个地方落了一个int,然后又加了一个无解的特判,60。。。这就很迷,最后,我突然发现我初始给附的初始值memset(f,127,sizeof(f))好像比1LL<<60小不少,然后改完才AC。。。

这个题犯了我近期所有犯过的错误。。。还是要仔细一点啊。

题干

Description

你有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是不允许的,因 为相同的数不许配对。
Input

第一行为一个正整数n,接下来是n 行,每行两个整数Ai和Bi,保证所有 Ai各不相同,Bi也各不相同。
Output

输出一个整数,即配对整数的差的绝对值之和的最小值。如果无法配对,输 出-1。
Sample Input
3

3 65

45 10

60 25
Sample Output
32
HINT

1 <= n <= 10^5,Ai和Bi均为1到10^6之间的整数。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const long long INF = 1LL << 60;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
ll f[100005];
int n;
ll a[100005],b[100005];
ll judge(int x,int y)
{
    if(a[x] == b[y])
        return INF;
    else
        return abs(a[x] - b[y]);
}
int main()
{
    read(n);
    duke(i,1,n)
    {
        f[i] = INF;
    }
    duke(i,1,n)
    {
        read(a[i]);
        read(b[i]);
    }
    if(n == 1 && a[1] == b[1])
    {
        printf("-1\n");
        return 0;
    }
    sort(a + 1,a + n + 1);
    sort(b + 1,b + n + 1);
    f[1] = judge(1,1);
    f[2] = min(judge(1,1) + judge(2,2),judge(1,2) + judge(2,1));
    duke(i,3,n)
    {
        f[i] = min(f[i],f[i - 1] + judge(i,i));
        f[i] = min(f[i],f[i - 2] + judge(i,i - 1) + judge(i - 1,i));
        f[i] = min(f[i],f[i - 3] + judge(i,i - 2) + judge(i - 1,i - 1) + judge(i - 2,i));
        f[i] = min(f[i],f[i - 3] + judge(i,i - 1) + judge(i - 1,i - 2) + judge(i - 2,i));
        f[i] = min(f[i],f[i - 3] + judge(i,i - 2) + judge(i - 1,i) + judge(i - 2,i - 1));
    }
    write(f[n]);
    return 0;
}

 

posted @ 2018-08-28 21:44  DukeLv  阅读(205)  评论(0编辑  收藏  举报