zoukankan      html  css  js  c++  java
  • BZOJ 1237 配对(DP)

    给出两个长度为n的序列。这两个序列的数字可以连边当且仅当它们不同,权值为它们的绝对值,求出这个二分图的最小权值完全匹配。没有输出-1.

    n<=1e5.用KM会TLE+MLE.

    如果连边没有限制的话,将两个序列排序一下显然就得到最优解了。

    考虑限制。则需要将排序后一些项交换。可以证明最优解最多交换距离为3。因为DP一下就可以了。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-9
    # define MOD 1000000000
    # define INF 0x7ffffffffffll
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=100005;
    //Code begin...
    
    int a[N], b[N];
    LL dp[N];
    
    LL get(int a, int b){return a==b?INF:abs(a-b);}
    int main ()
    {
        int n;
        scanf("%d",&n);
        FOR(i,1,n) scanf("%d%d",a+i,b+i);
        sort(a+1,a+n+1); sort(b+1,b+n+1);
        dp[1]=get(a[1],b[1]);
        if (n>=2) dp[2]=min(dp[1]+get(a[2],b[2]),get(a[1],b[2])+get(a[2],b[1]));
        FOR(i,3,n) {
            dp[i]=dp[i-1]+get(a[i],b[i]);
            dp[i]=min(dp[i],dp[i-2]+get(a[i],b[i-1])+get(a[i-1],b[i]));
            dp[i]=min(dp[i],dp[i-3]+get(a[i-2],b[i-1])+get(a[i-1],b[i])+get(a[i],b[i-2]));
            dp[i]=min(dp[i],dp[i-3]+get(a[i-2],b[i])+get(a[i-1],b[i-2])+get(a[i],b[i-1]));
            dp[i]=min(dp[i],dp[i-3]+get(a[i-2],b[i])+get(a[i-1],b[i-1])+get(a[i],b[i-2]));
        }
        if (dp[n]>=INF) puts("-1");
        else printf("%lld
    ",dp[n]);
        return 0;
    }
    View Code
  • 相关阅读:
    树---数据结构
    B+树索引
    对大文件排序
    快速拍粗和冒泡排序
    TCp
    TCP通信粘包问题分析和解决(全)(转)
    linkhashmap实现原理
    spring中用到的设计模式
    linux查看进程和线程的命令
    Shell编程入门(第二版)(中)
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6764312.html
Copyright © 2011-2022 走看看