首先贴一下这道题的BNU地址,UVA地址自己找吧。

http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=11852

题意:这道题的意思就是,给你N个棋子的坐标,这些棋子的走法是象棋中的马的走法。然后再给你N个坐标终点。

问所有的棋子走到其中一个坐标上,不能有重复,最少的步数是多少。

思路:这道题直接搜显然爆,因为他的坐标范围都是int ,所以我们就要考虑怎么处理出两个点之间的最短步数。

我直接把问题扔给队友了,然后他推出了一条公式,太神不能多说。

问题简化成给你两个点(x , y ) ,(x1 , y1),求这两个点之间最少需要多少步。

然后他经过一系列的数学推导,就搞定了。

过程我也不会,等下看代码。

然后接下来每个棋子到每个终点坐标的距离都处理出来了。

那么根据N = 15 。那么很显然状压DP就可以搞定,求出最小值。

但是考虑到每个棋子只有一个位置,那么很显然棋子和终点位置是二分图,那么很显然我们可以用最小权匹配来搞这个问题。

KM的姿势比状压优美许多。

#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Max 2505
#define FI first
#define SE second
#define ll long long
#define PI acos(-1.0)
#define inf 1ll << 60ll
#define LL(x) ( x << 1 )
#define bug puts("here")
#define PII pair<int,int>
#define RR(x) ( x << 1 | 1 )
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i ) using namespace std; ll f(ll x,ll y) {//推出来的,太神不多说
x=abs(x);
y=abs(y);
if(x>y) {
swap(x,y);
}
if(x==0&&y==1) {
return 3;
}
if(x==2&&y==2) {
return 4;
}
ll z=max((y+1)/2ll,(x+y+2)/3ll);
if((z-x-y)&1) {
z++;
}
return z;
}
int n ;
ll x[22] , y[22] ;
ll xx[22] , yy[22] ;
ll Map[22][22] ;
ll lx[22] ,ly[22] ,linkx[22] , linky[22] ;
bool visx[22] , visy[22] ;
int find(int now){
visx[now] = 1 ;
for (int i = 0 ; i < n ; i ++ ){
if(!visy[i] && Map[now][i] - lx[now] - ly[i] == 0){
visy[i] = 1 ;
if(linky[i] == -1 || find(linky[i])){
linkx[now] = i ;
linky[i] = now ;
return 1 ;
}
}
}
return 0 ;
}
ll KM(){
mem(linkx , -1) ;
mem(linky , -1) ;
mem(ly ,0) ;
for (int i = 0 ; i < n ; i ++ ){
while(1){
mem(visx ,0) ;mem(visy , 0) ;
if(find(i))break ;
ll d = inf ;
for (int j = 0 ; j < n ; j ++ ){
if(visx[j])
for (int k = 0 ; k < n ; k ++ ){
if(!visy[k])
d = min(d , Map[j][k] - lx[j] - ly[k]) ;
}
}
for (int j = 0 ; j < n ; j ++ ){
if(visx[j])lx[j] += d ;
if(visy[j])ly[j] -= d ;
}
}
}
ll ans = 0 ;
for (int i = 0 ; i < n ; i ++ ){
if(linky[i] != -1 )ans += Map[linky[i]][i] ;
}
return ans ;
}
int main() {
int ca = 0 ;
while(cin >> n , n ){
for (int i = 0 ; i < n ; i ++ )cin >> x[i] >> y[i] ;
for (int i = 0 ; i < n ; i ++ )cin >> xx[i] >> yy[i] ;
for (int i = 0 ; i < n ; i ++ )lx[i] = inf ;
for (int i = 0 ; i < n ; i ++ ){
for (int j = 0 ; j < n ; j ++ ){
Map[i][j] = f(x[i] - xx[j] , y[i] - yy[j]) ;
lx[i] = min(lx[i] , Map[i][j]) ;
}
}
cout << ++ ca << ". " ;
cout << KM() << endl;
}
return 0 ;
}

UVALIVE 4970 最小权匹配的更多相关文章

  1. HDU(1853),最小权匹配,KM

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Other ...

  2. Poj(3686),最小权匹配,多重匹配,KM

    题目链接 The Windy's | Time Limit: 5000MS | Memory Limit: 65536K | | Total Submissions: 4939 | Accepted: ...

  3. POJ 3565 Ants (最小权匹配)

    题意 给出一些蚂蚁的点,给出一些树的点,两两对应,使他们的连线不相交,输出一种方案. 思路 一开始没想到怎么用最小权匹配--后来发现是因为最小权匹配的方案一定不相交(三角形两边之和大于第三边)--还是 ...

  4. POJ 2400 最小权匹配

    吐槽:首先,这道题的输入居然是错的.要将上下两个矩阵的位置换一下才可以出样例,也就是上面那个矩阵是employee对Supervisor的打分,下面那个矩阵才是Supervisor对employee的 ...

  5. poj 2516(拆点+最小权匹配)

    题目链接:http://poj.org/problem?id=2516 思路:考虑某种货物,由于某个订货商可能接受来自不同地区的货物,而某一地区的货物也可能送给不同的订货商,显然不能直接进行匹配,必须 ...

  6. poj 3686(拆点+最小权匹配)

    题目链接:http://poj.org/problem?id=3686 思路:显然工件为X集,机器为Y集合.由于每个机器一次只能加工一个部件,因此我们可以将一台机器拆成N个点,至于部件与机器之间连多大 ...

  7. poj 2195(KM求最小权匹配)

    题目链接:http://poj.org/problem?id=2195 思路:我们都知道KM使用来求最大权匹配的,但如果要求最小权匹配,只需把图中的权值改为负值,求一次KM,然后权值和取反即可. ht ...

  8. 【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)

    [POJ 2400] Supervisor, Supervisee(KM求最小权匹配) Supervisor, Supervisee Time Limit: 1000MS   Memory Limit ...

  9. 【POJ 2195】 Going Home(KM算法求最小权匹配)

    [POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submiss ...

随机推荐

  1. 一个简单的ORM制作(SQL帮助类)

    一个简单的ORM制作大概需要以下几个类: SQL执行类 CURD操作类 其他酱油类 先从SQL执行类说起,可能会涉及数据库的迁移等问题,所以需要定义一个接口以方便迁移到其他数据库, 事务没提供命名,若 ...

  2. BZOJ2229: [Zjoi2011]最小割

    题解: 真是一道神题!!! 大家还是围观JZP的题解吧(网址找不到了...) 代码: #include<cstdio> #include<cstdlib> #include&l ...

  3. hdu 4674 Trip Advisor(缩点+倍增lca)

    花了一天半的时间,才把这道题ac= = 确实是道好题,好久没敲这么长的code了,尤其是最后的判定,各种销魂啊~ 题目中给出的条件最值得关注的就是:每个点最多只能在一个环内->原图是由一个个边连 ...

  4. matlab中,计算,记录,程序运行,起始,结束 时间,间隔 &matlab中 tic,toc函数的用法

    Tic和toc函数可以计算运行一段时间的代码. 例如: clc tic d=zeros(1,10000); for i=1:10000 d(i)=i; end toc tic c=1; for i=1 ...

  5. android中ViewHolder通用简洁写法

    public class ViewHolder {     // I added a generic return type to reduce the casting noise in client ...

  6. IO的阻塞、非阻塞、同步、异步

  7. 【转】ACE开发环境搭建

    Windows平台 1)        下载ACE源码 ACE官方网址:http://www.cs.wustl.edu/~schmidt/ACE.html ACE下载地址:http://downloa ...

  8. 指针和引用的比较(P105)

    指针和引用的比较? 虽然使用引用和指针都可间接访问另一个值,但它们之间有两个重要区别. 第一个区别在于引用总是指向某个对象:定义引用时没有初始化是错误的. 第二个重要区别则是赋值行为的差异:给引用赋值 ...

  9. HDU5777 domino (BestCoder Round #85 B) 思路题+排序

    分析:最终的结果肯定会分成若干个区间独立,这些若干个区间肯定是独立的(而且肯定是一边倒,左右都一样) 这样想的话,就是如何把这n-1个值分成 k份,使得和最小,那么就是简单的排序,去掉前k大的(注意l ...

  10. Tableau学习笔记之三

    1.Tableau可以连接多种多样的数据以及数据库,例如txt,xls,mdb,sql server,oracle等等 2.Tableau还可以从剪贴板上粘贴数据 3.维度和度量的理解: 1)维度即表 ...