首先贴一下这道题的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. poj 1703 Find them, Catch them(并查集)

    题目:http://poj.org/problem?id=1703 题意:一个地方有两个帮派, 每个罪犯只属于其中一个帮派,D 后输入的是两个人属于不同的帮派, A后询问 两个人是否属于 同一个帮派. ...

  2. 宏os_file_read_func

    # define os_file_read(file, buf, offset, offset_high, n) \ os_file_read_func(file, buf, offset, offs ...

  3. UVa 11916 (离散对数) Emoogle Grid

    因为题目要求同列相邻两格不同色,所以列与列之间不影响,可以逐列染色. 如果一个格子的上面相邻的格子,已经被染色则染这个格子的时候,共有k-1中选择. 反过来,如果一个格子位于第一列,或者上面相邻的格子 ...

  4. UVa 10375 (唯一分解定理) Choose and divide

    题意: 求组合数C(p, q) / C(r, s)结果保留5为小数. 分析: 先用筛法求出10000以内的质数,然后计算每个素数对应的指数,最后再根据指数计算答案. #include <cstd ...

  5. asp.net 2.0中新增的web.config的默认namespace功能 (转)

    看上去这个题目比较长,但实际上,我在看资料时发现,这就是说,在asp.net 2.0中,只需要在web.config里定义你要用的那些namespace,则在aspx页面中就不需要再象1.1那样,用 ...

  6. [Sciter系列] MFC下的Sciter–3.Sciter脚本与底层交互

    [Sciter系列] MFC下的Sciter–3.Sciter脚本与底层交互,脚本调用底层自定义的方法函数. 本系列文章的目的就是一步步构建出一个功能可用,接口基本完善的基于MFC框架的SciterF ...

  7. liunx下mysql数据库使用之三范式,关系模型设计注意项,安装目录结构

    数据库的三范式第一范式===>每行记录的属性,是原子的,拆到不可拆为止.===>例如:一个人的籍贯,可以拆分为,省,市,县,乡,村 第二范式===>每行记录的非主属性(非主键属性), ...

  8. 【RMQ问题】求数组区间最大值,NYOJ-1185-最大最小值

    转自:http://blog.csdn.net/lilongherolilong/article/details/6624390 先挖好坑,明天该去郑轻找虐 RMQ(Range Minimum/Max ...

  9. java web 学习八(HttpServletResponse对象2)

    一.HttpServletResponse常见应用——生成验证码 1.1.生成随机图片用作验证码 生成图片主要用到了一个BufferedImage类,

  10. Delphi 操作word 表格

    var wordApp, WordDoc, WrdSelection, wrdtable: variant; strAdd: string; wdPar,wdRange:OleVariant; iCo ...