题意:

一个n * n的棋盘上放着n个棋子,现在要求把这n个棋子用最少的步数移到同一条直线上,即同一列同一行或者同一对角线(两条)。输出最少的步数(只能往四个方向移动,即正东,正西,正南,正北)。

思路:

每个棋子唯一对应一个格子,每个棋子不能在同一个格子,那么就相当于一个二分图(强行二分图)。

因为n很小,所以可以枚举每一行,每一列,两条对角线,然后每个点移动到每一条直线的每一个格子都有一个距离,那么这个点就向格子连一条权值为距离的边,这个问题就转化成了求所有最佳完美的匹配中的最小值,用KM算法。

因为我们求的是最小步数,所以求的是带权二分图的最小匹配

求最小匹配,就将每一条边的权值取反,然后求最大匹配,再将最后的结果取反就得到了最小匹配的结果。

复杂度为O(n^4)。

注意:输出很坑,每一个答案后都有一个换行,并不是两个中间输出一个,也就是说,最后一个后面也有换行。

代码:

 #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std; const int N = ;
const int inf = 0x3f3f3f3f; int love[N][N];
int lx[N],ly[N];
bool visx[N],visy[N];
int match[N];
int slack[N]; struct node
{
int x,y; node(int aa,int bb)
{
x = aa;
y = bb;
}
}; vector<node> vn; int mabs(int x)
{
return x >= ? x : -x;
} bool dfs(int u,int n)
{
visx[u] = ; for (int i = ;i <= n;i++)
{
if (visy[i]) continue; int gap = lx[u] + ly[i] - love[u][i]; if (gap == )
{
visy[i] = ; if (match[i] == - || dfs(match[i],n))
{
match[i] = u;
return true;
}
}
else
{
slack[i] = min(gap,slack[i]);
}
} return false;
} int km(int n)
{
memset(match,-,sizeof(match));
memset(ly,,sizeof(ly)); for (int i = ;i <= n;i++)
{
lx[i] = love[i][]; for (int j = ;j <= n;j++)
{
lx[i] = max(lx[i],love[i][j]);
}
} for (int i = ;i <= n;i++)
{
memset(slack,inf,sizeof(slack)); while ()
{
memset(visx,,sizeof(visx));
memset(visy,,sizeof(visy)); if (dfs(i,n)) break; int d = inf; for (int j = ;j <= n;j++)
{
if (!visy[j]) d = min(d,slack[j]);
} for (int j = ;j <= n;j++)
{
if (visx[j]) lx[j] -= d; if (visy[j]) ly[j] += d;
}
} } int res = ; for (int i = ;i <= n;i++)
{
res += love[match[i]][i];
} return res;
} int main()
{
int n;
int kase = ; while (scanf("%d",&n) != EOF && n)
{
vn.clear(); for (int i = ;i < n;i++)
{
int a,b; scanf("%d%d",&a,&b); vn.push_back(node(a,b));
} //if (kase) printf("\n"); int ans = 1e8; for (int i = ;i <= n;i++)
{
for (int j = ;j < vn.size();j++)
{
for (int k = ;k <= n;k++)
{
int dx = mabs(vn[j].x - i);
int dy = mabs(vn[j].y - k);
love[j+][k] = -(dx + dy);
}
} int tmp = -km(n); //printf("%d **\n",tmp); ans = min(tmp,ans);
} for (int i = ;i <= n;i++)
{
for (int j = ;j < vn.size();j++)
{
for (int k = ;k <= n;k++)
{
int dy = mabs(vn[j].y - i);
int dx = mabs(vn[j].x - k);
love[j+][k] = -(dx + dy);
}
} int tmp = -km(n); ans = min(tmp,ans); //printf("%d **\n",tmp);
} for (int i = ;i <= n;i++)
{
for (int j = ;j < vn.size();j++)
{
int dx = mabs(vn[j].x - i);
int dy = mabs(vn[j].y - i); love[j+][i] = -(dx + dy);
}
} ans = min(ans,-km(n)); for (int i = ;i <= n;i++)
{
for (int j = ;j < vn.size();j++)
{
int dx = mabs(vn[j].x - i);
int dy = mabs(vn[j].y - (n - i + )); love[j+][i] = -(dx + dy);
}
} ans = min(ans,-km(n)); printf("Board %d: %d moves required.\n\n",++kase,ans);
} return ;
}

uvalive 3276 The Great Wall Game的更多相关文章

  1. UVALive 5097 Cross the Wall

    贪心思想,$dp$,斜率优化. 首先将人按照$w$从大到小排序,如果$w$一样,按$h$从大到小排.这样一来,某位置之后,比该位置$h$小的都是不需要考虑的. 因此,形成了如下图所示的结果: 即第一个 ...

  2. [kuangbin带你飞]专题二十 斜率DP

            ID Origin Title   20 / 60 Problem A HDU 3507 Print Article   13 / 19 Problem B HDU 2829 Lawr ...

  3. KUANGBIN带你飞

    KUANGBIN带你飞 全专题整理 https://www.cnblogs.com/slzk/articles/7402292.html 专题一 简单搜索 POJ 1321 棋盘问题    //201 ...

  4. 【转】斜率优化DP和四边形不等式优化DP整理

    (自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...

  5. [kuangbin带你飞]专题1-23题目清单总结

    [kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...

  6. ACM--[kuangbin带你飞]--专题1-23

    专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 FliptilePOJ 1426 Find T ...

  7. UVALive 4425 Another Brick in the Wall 暴力

    C - Another Brick in the Wall Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & ...

  8. UVALive 2453 Wall (凸包)

    题意:给你一个多边形的城堡(多个点),使用最短周长的城墙将这个城堡围起来并保证城墙的每个点到城堡上的每个点的距离都不小于l 题解:因为两点间的直线一定比折线短,所以这样做 先使用所有点求得一个凸包,接 ...

  9. UVALive 5066 Fire Drill BFS+背包

    H - Fire Drill Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Sta ...

随机推荐

  1. idea+maven+springboot+mybatis+springmvc+shiro

    springboot就是把创建项目简单化,省去了以往的配置mybatis.springmvc的繁琐过程. 搭建web应用三个主要功能,请求和响应,数据库交互,权限配置. 一.idea创建项目 (1) ...

  2. 洛谷P4247 序列操作 [清华集训] 线段树

    正解:线段树 解题报告: 传送门! 通过这题我get了一个神奇的,叫,线段树五问的东西hhhh 听起来有点中二但感觉真正做题的时候还是比较有用的,,,?感觉会让条理清晰很多呢,所以放一下QwQ →每个 ...

  3. 洛谷P3234 抄卡组 [HNOI2014] 字符串hash

    正解:字符串hash 解题报告: 传送门! 字符串hash是字符串匹配中很常见的一个方法,原理也很好懂,这里就不做太多阐述辣有时间放到hash笔记里面去QAQ 题意不说了挺好理解的,自带一句话概括好评 ...

  4. XSL常用用法语句

    1.xsl的开始语句 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Tra ...

  5. 关于webpack,babel,以及es6和commonJS之间的联系(转)

    add by zhj: babel是将es6转为es5,而webpack从名字也能看出来,是一个打包工具,根据文件之间的依赖关系,将文件进行打包 原文:https://blog.csdn.net/a2 ...

  6. file 选取文件/文件夹

    一般网页上传文件大家都会用到这个标签 <input type="file" id="file_input"/> 我们可以通过这个标签选取文件,使用j ...

  7. Verilog如何从外部更改模块内参数

    例如有一个模块 module x(a,b,c); input a,b; output c; 'd0, h=9'd3; ...... endmodule 两种解决方法: 1.使用带有参数值的模块实例语句 ...

  8. aws的安全组

    aws有安全组来控制进入和去除的规则. 入站:就是外网访问你出站:就是你访问外网用户可以创建入站和出站规则,从而阻挡或者允许特定程序或者端口进行连接;用户可以将规则应用于一组程序.端口或者服务,也可以 ...

  9. MongoDB 新建数据库和集合 查询集合

    MongoDB语法是原生ORM,根本不存在sql语句 创建数据库:这里和一般的关系型数据库一样,都要先建立一个自己的数据库空间 新建数据库db1 > use db1 switched to db ...

  10. what's the python之可迭代对象、迭代器与生成器(附面试题)

    可迭代对象 字符串.列表.元祖.集合.字典都是可迭代的,数字是不可迭代的.(可以用for循环遍历取出内部元素的就是可迭代的) 如何查看一个变量是否为可迭代: from collections impo ...