BZOJ 1237 配对
Description
你有\(n\)个整数\(A_{i}\)和\(n\)个整数\(B_{i}\)。你需要把它们配对,即每个\(A_{i}\)恰好对应一 个\(Bp_{i}\)。要求所有配对的整数差的绝对值之和尽量小,但不允许两个相同的数配对。例如\(A=\lbrace 5,6,8 \rbrace\),\(B=\lbrace 5,7,8 \rbrace\),则最优配对方案是\(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
\(30\%\)的数据满足:\(n \le 10^{4}\)
\(100\%\)的数据满足:\(1 \le n \le 10^{5}\),\(A_{i}\)和\(B_{i}\)均为\(1\)到\(10^{6}\)之间的整数。
难得又一道自己想出的题目。
首先如果没有相同的数字不能同时配对,那么排序之后两两配对一定是最优的。那么我们在满足题目限制一定也要尽可能的满足题目的限制,相邻两个进行交换。
我们令\(pos_{i}\)表示前第\(i\)个排序后数字相同配对的位置,\(f_{i,0/1}\)表示前\(i\)个数字相同的配对,使其合法的最小增加代价(\(0\)表示与前面的交换,\(1\)表示与后面的交换)。转移有这样以下的几个:
\]
当\(pos_{i-1} \ge pos_{i}-1\)时$$f_{i,0} = f_{i-1,0}+calc(pos_{i}-1,pos_{i})$$
否则$$f_{i,0} = min(f_{i-1,0},f_{i-1,1})+calc(pos_{i}-1,pos_{i})$$
产生分歧的原因是如果\(pos_{i-1} \ge pos_{i}-1\),那么如果\(i-1\)号非法配对与右边的交换,\(i\)号与左边的交换代价计算就会出错。
当\(i \ge 2\)并且\(pos_{i}=pos_{i-1}+1\),我们可以两个非法的进行交换,得到以下的转移:
当\(pos_{i-2} \ge pos_{i-1}-1\)时,$$f_{i,0} = min(f_{i,0},f_{i-2,0}+calc(pos_{i-1},pos_{i}))$$
否则$$f_{i,0} = min(f_{i,0},min(f_{i-2,0},f_{i-2,1})+calc(pos_{i-1},pos_{i}))$$
分歧的原因同上。
以上转移\(calc(a,b)\)为计算交换\(a,b\)位置增加代价的函数。
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef long long ll;
#define inf (1LL<<60)
#define maxn 100010
int n,pos[maxn],tot; ll sum,A[maxn],B[maxn],f[maxn][2];
inline ll calc(int a,int b)
{
if (!a||!b) return inf; if (a > n||b > n) return inf;
return (abs(A[a]-B[b])+abs(A[b]-B[a]))-(abs(A[a]-B[a])+abs(A[b]-B[b]));
}
inline void dp()
{
memset(f,0x7,sizeof(f));
f[0][0] = f[0][1] = 0;
for (int i = 1;i <= tot;++i)
{
f[i][1] = min(f[i-1][0],f[i-1][1])+calc(pos[i],pos[i]+1);
if (pos[i-1]<pos[i]-1) f[i][0] = min(f[i-1][0],f[i-1][1])+calc(pos[i]-1,pos[i]);
else f[i][0] = f[i-1][0]+calc(pos[i]-1,pos[i]);
if (i >= 2&&pos[i] == pos[i-1]+1)
{
if (pos[i-2]<pos[i-1]-1) f[i][0] = min(f[i][0],min(f[i-2][0],f[i-2][1])+calc(pos[i-1],pos[i]));
else f[i][0] = min(f[i][0],f[i-2][0]+calc(pos[i-1],pos[i]));
}
}
}
int main()
{
freopen("1237.in","r",stdin);
freopen("1237.out","w",stdout);
scanf("%d",&n); for (int i = 1;i <= n;++i) scanf("%lld %lld",A+i,B+i);
A[0] = A[n+1] = inf; pos[0] = -100;
sort(A+1,A+n+1); sort(B+1,B+n+1);
for (int i = 1;i <= n;++i)
{
sum += abs((A[i]-B[i]));
if (A[i] == B[i]) pos[++tot] = i;
}
dp(); printf("%lld",sum+min(f[tot][0],f[tot][1]));
fclose(stdin); fclose(stdout);
return 0;
}
BZOJ 1237 配对的更多相关文章
- BZOJ 1237 配对(DP)
给出两个长度为n的序列.这两个序列的数字可以连边当且仅当它们不同,权值为它们的绝对值,求出这个二分图的最小权值完全匹配.没有输出-1. n<=1e5.用KM会TLE+MLE. 如果连边没有限制的 ...
- bzoj 1237 [SCOI2008]配对 贪心+dp
思路:dp[ i ] 表示 排序后前 i 个元素匹配的最小值, 我们可以发现每个点和它匹配的点的距离不会超过2,这样就能转移啦. #include<bits/stdc++.h> #defi ...
- BZOJ 1786 配对(DP)
如果我们直接令dp[i][j]为前i个位置第i个位置填j所产生的逆序对的最少数.这样是不满足无后效性的. 但是如果发现对于两个-1,如果前面的-1填的数要大于后面的-1填的数.容易证明把他们两交换结果 ...
- dp专练
dp练习. codevs 1048 石子归并 区间dp #include<cstdio> #include<algorithm> #include<cstring> ...
- bzoj千题计划179:bzoj1237: [SCOI2008]配对
http://www.lydsy.com/JudgeOnline/problem.php?id=1237 如果没有相同的数不能配对的限制 那就是排好序后 Σ abs(ai-bi) 相同的数不能配对 交 ...
- BZOJ 4205: 卡牌配对
4205: 卡牌配对 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 173 Solved: 76[Submit][Status][Discuss] ...
- 图论(费用流):BZOJ 4514 [Sdoi2016]数字配对
4514: [Sdoi2016]数字配对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 820 Solved: 345[Submit][Status ...
- BZOJ 4514: [Sdoi2016]数字配对 [费用流 数论]
4514: [Sdoi2016]数字配对 题意: 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数 ...
- BZOJ.4514.[SDOI2016]数字配对(费用流SPFA 二分图)
BZOJ 洛谷 \(Solution\) 很显然的建二分图后跑最大费用流,但有个问题是一个数是只能用一次的,这样二分图两部分都有这个数. 那么就用两倍的.如果\(i\)可以向\(j'\)连边,\(j\ ...
随机推荐
- Memcached笔记——(四)应对高并发攻击【转】
http://snowolf.iteye.com/blog/1677495 近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最 ...
- [TypeScript] Loading Compiled TypeScript Files in Browser with SystemJS
TypeScript outputs JavaScript, but what are you supposed to do with it? This lesson shows how to tak ...
- 【转】学习Flex ActionScript 3.0 强烈推荐电子书
学习Flex ActionScript 3.0 强烈推荐电子书 AdvancED ActionScript 3.0 Animation(<Make things move>姐妹篇,强烈推 ...
- Apache Kafka: Next Generation Distributed Messaging System---reference
Introduction Apache Kafka is a distributed publish-subscribe messaging system. It was originally dev ...
- CentOS更换python版本后,yum不可用的问题
因为yum调用了python,他的启动程序/usr/bin/yum就是一个python脚本 yum是不兼容 Python 2.7的,所以yum不能正常工作,我们需要指定 yum 的Python版本 将 ...
- python学习笔记--Django入门二 Django 的模板系统
为了使网站更干净简洁更容易维护,页面的设计和Python的代码必须分离开.我们可以使用Django的 模板系统 (Template System)来实现这种模式. 几个简单的模板标签(tag): ...
- Xcode4快速Doxygen文档注释 — 简明图文教程
转自:http://blog.csdn.net/totogo2010/article/details/9100767 准备2个文件: 文件一,ThisService.app 文件二,Doxygen.r ...
- Install-User.ps1
Install-User.ps1 function Install-User { param( [Parameter()] [string]$ComputerName = $env:computern ...
- 大数据应用:五大地区喜新厌旧游戏APP类别之比较与分析
今天,我们来分享点不一样的资讯.....游戏APP之喜新厌旧排行榜!! 前阵子笔者开发了一套系统可以用来收集亚洲五大地区上架APP的每日排名信息,希望观察出五大地区在APP上的喜好和使用程度之间的相异 ...
- 基于PHP的cURL快速入门
cURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.最爽的是,PHP也支持 cURL 库.本文将介绍 cURL 的一些高级特性,以及在PHP中如 ...