zoukankan      html  css  js  c++  java
  • 【题解】SCOI2008配对

    贪心+dp~观察数据,发现一个规律:将数字排序之后,最优匹配只可能产生在该数字和与它距离不超过二的数字之间。

    所以可以用dp[i]代表前i个数(排序)匹配的最小差值,之后暴力选出该新数应该如何匹配。

    以及题目保证A[i](B[i])中所有数字互不相同,这是为了避免一种情况的出现:

    1 1 5 5

    5 5 1 1

    此时的最优解距离就超过了二啦。这种情况我并没有想到解,也很好奇是不是能够有接受这种情况的算法。

    以下我丑丑的代码……(捂脸)、+INF要开大大大大大大大大大!

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 2500000
    #define INF 9999999999LL
    #define int long long
    int dp[maxn], a[maxn], b[maxn], n, mark[maxn], cnt[maxn];
    
    int read()
    {
        int x = 0;
        char c;
        c = getchar();
        while(c < '0' || c > '9') c = getchar();
        while(c >='0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x;
    }
    
    int abs(int x, int y)
    {
        if(x == y) return INF;
        else return (x - y) >= 0 ? x - y : y - x;
    }
    
    signed main()
    {
        n = read();
        for(int i = 1; i <= n; i ++) 
            a[i] = read(), b[i] = read();
        for(int i = 1; i <= n; i ++) dp[i] = INF;
        sort(a + 1, a + 1 + n);
        sort(b + 1, b + 1 + n);
        for(int i = 1; i <= n; i ++)
        {
            mark[i] += mark[i - 1];
            if(a[i] == a[i - 1]) cnt[i] = cnt[i - 1] + 1;
            else cnt[i] = 1;
            if(a[i] == b[i]) mark[i] ++;
            if(a[i] != b[i]) dp[i] = dp[i - 1] + abs(a[i], b[i]);
            if(i >= 2)
            {
                if(a[i] != a[i - 1]) 
                    dp[i] = min(dp[i - 2] + abs(a[i], b[i - 1]) + abs(b[i], a[i - 1]), dp[i]);
                if(i >= 3 && mark[i] - mark[i - 3] >= 2)
                {
                    int tem = abs(a[i], b[i - 2]) + abs(a[i - 1], b[i]) + abs(a[i - 2], b[i - 1]);
                    tem = min(tem, abs(a[i], b[i - 1]) + abs(a[i - 1], b[i - 2]) + abs(a[i - 2], b[i]));
                    tem = min(tem, abs(a[i], b[i - 2]) + abs(a[i - 1], b[i - 1]) + abs(a[i - 2], b[i]));
                    dp[i] = min(dp[i], dp[i - 3] + tem);
                }
            }
        }
        if(dp[n] >= INF) printf("-1
    ");
        else printf("%lld
    ", dp[n]);
        return 0;
    }
  • 相关阅读:
    从TCP三次握手说起——浅析TCP协议中的疑难杂症
    动态绑定是如何实现的?
    C++对象的内存模型
    C/C++关键字
    libevent库介绍--事件和数据缓冲
    libevent编程疑难解答
    大型工程多个目录下的Makefile写法
    C++中的RAII机制
    C++中的智能指针
    二叉树的非递归遍历
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/8407637.html
Copyright © 2011-2022 走看看