zoukankan      html  css  js  c++  java
  • bzoj 1237 配对

    Written with StackEdit.

    Description

    你有(n) 个整数(A_i)(n) 个整数(B_i)。你需要把它们配对,即每个(A_i)恰好对应一 个(B_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) 行,每行两个整数(A_i)(B_i),保证所有 (A_i)各不相同,(B_i)也各不相同

    Output

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

    Sample Input

    3
    3 65
    45 10
    60 25

    Sample Output

    32

    HINT

    (1 <= n <= 10^5)(A_i)(B_i)均为(1)(10^6)之间的整数。

    Solution

    第一眼费用流 然而看数据范围 显然不可做...

    • 考虑先将(A)(B)从小到大排序.
    • 若没有相同的不可取的限制,显然直接贪心,(A_i)(B_i).
    • 注意到,(A_i)各不相同,(B_i)也各不相同.所以如果(A_i=B_i),那么(A_i)肯定与(B_{i-1},B_{i-2})都不相同.
    • 这样容易发现,(A_{i-2},A_{i-1},A_{i},B_{i-2},B_{i-1},B_{i})两两配对是一定有合法方案的.
    • (f[i])表示将(A_1)(A_i),(B_1)(B_i)两两配对的最小花费.
    • 枚举,(A_{i-2},A_{i-1},A_{i},B_{i-2},B_{i-1},B_{i})两两配对的方式转移即可.
    • 注意边界(f[1],f[2].)以及特判无解.
    #include<bits/stdc++.h>
    #define inf 1e18
    using namespace std;
    typedef long long LoveLive;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		{
    			fh=-1;
    			jp=getchar();
    		}
    	while (jp>='0'&&jp<='9')
    		{
    			out=out*10+jp-'0';
    			jp=getchar();
    		}
    	return out*fh;
    }
    const int MAXN=1e5+10;
    int a[MAXN],b[MAXN];
    inline LoveLive calc(int x,int y)
    {
    	return x==y?inf:abs(x-y);
    }
    inline void upd(LoveLive &x,LoveLive y)
    {
    	if(y<x)
    		x=y;
    }
    int n;
    LoveLive f[MAXN];
    void init()
    {
    	f[0]=0;
    	f[1]=calc(a[1],b[1]);
    	f[2]=min(f[1]+calc(a[2],b[2]),calc(a[1],b[2])+calc(a[2],b[1]));
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)
    		a[i]=read(),b[i]=read();
    	if(n==1 && a[1]==b[1])
    		{
    			puts("-1");
    			return 0;
    		}
    	sort(a+1,a+1+n);
    	sort(b+1,b+1+n);
    	init();
    	for(int i=3;i<=n;++i)
    		{
    			f[i]=inf;
    			upd(f[i],f[i-1]+calc(a[i],b[i]));
    			upd(f[i],f[i-2]+calc(a[i-1],b[i])+calc(a[i],b[i-1]));
    			upd(f[i],f[i-3]+calc(a[i],b[i-2])+calc(a[i-1],b[i-1])+calc(a[i-2],b[i]));
    			upd(f[i],f[i-3]+calc(a[i],b[i-1])+calc(a[i-1],b[i-2])+calc(a[i-2],b[i]));
    			upd(f[i],f[i-3]+calc(a[i],b[i-2])+calc(a[i-1],b[i])+calc(a[i-2],b[i-1]));
    		}
    	printf("%lld
    ",f[n]);
    	return 0;
    }
    

    开long long.

  • 相关阅读:
    我的第一篇博客
    1.2 位于Shell脚本第一行的#!
    1.1 一个简单的脚本
    JDK与CGlib动态代理的实现
    解决Sublime Text3中文显示乱码问题
    多线程讲解
    (转)Spring中@Async用法总结
    (转)spring boot注解 --@EnableAsync 异步调用
    Spring Boot中的注解
    (转)如何用Maven创建web项目(具体步骤)
  • 原文地址:https://www.cnblogs.com/jklover/p/10063571.html
Copyright © 2011-2022 走看看