uvalive 3276 The Great Wall Game
题意:
一个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的更多相关文章
- UVALive 5097 Cross the Wall
贪心思想,$dp$,斜率优化. 首先将人按照$w$从大到小排序,如果$w$一样,按$h$从大到小排.这样一来,某位置之后,比该位置$h$小的都是不需要考虑的. 因此,形成了如下图所示的结果: 即第一个 ...
- [kuangbin带你飞]专题二十 斜率DP
ID Origin Title 20 / 60 Problem A HDU 3507 Print Article 13 / 19 Problem B HDU 2829 Lawr ...
- KUANGBIN带你飞
KUANGBIN带你飞 全专题整理 https://www.cnblogs.com/slzk/articles/7402292.html 专题一 简单搜索 POJ 1321 棋盘问题 //201 ...
- 【转】斜率优化DP和四边形不等式优化DP整理
(自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...
- [kuangbin带你飞]专题1-23题目清单总结
[kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...
- ACM--[kuangbin带你飞]--专题1-23
专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 FliptilePOJ 1426 Find T ...
- UVALive 4425 Another Brick in the Wall 暴力
C - Another Brick in the Wall Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & ...
- UVALive 2453 Wall (凸包)
题意:给你一个多边形的城堡(多个点),使用最短周长的城墙将这个城堡围起来并保证城墙的每个点到城堡上的每个点的距离都不小于l 题解:因为两点间的直线一定比折线短,所以这样做 先使用所有点求得一个凸包,接 ...
- UVALive 5066 Fire Drill BFS+背包
H - Fire Drill Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Sta ...
随机推荐
- 如何在Win10上永久禁用Windows Defender Antivirus
1.使用Windows键+ R键盘快捷键打开运行命令. 2.键入regedit,然后单击确定以打开注册表. 3.浏览以下路径: HKEY_LOCAL_MACHINE/SOFTWARE/Policies ...
- 内核block机制
内核版本:linux2.6.22.6 硬件平台:JZ2440 驱动源码 block_ipc_poll_key_int_drv.c : #include <linux/module.h> # ...
- c语言指针应用
指针变量指向数组元素: #import <stdio.h> int main() { int a[10]={1,2,3,4,5,6,7,8,9,0}; int *p; p=a; for ( ...
- OC屏幕手势解锁
感觉屏幕解锁好像很牛的样子,所以试着写了一个,代码很简单,手势用到的也是原生的,如果该代码帮助了你,记得点赞,如果该代码有任何问题,也可以随时和我联系.改代码用到的两张图片,是我随便找的两张,可以自行 ...
- AFNetWorking上传JSON串
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; manager.responseSerializer = [AFJSON ...
- 014-通过JDB调试,通过HSDB来查看HotSpot VM的运行时数据
一.JDB调试 在预发环境下进行debug时,时常因为工具和环境的限制,导致debug体验非常差,那么有什么方法能够简化我们进行debug的体验吗?JDB就是一种. JDB ...
- 对Python源码加密及反编译前后对比
关于python的加密 目前软件开发商对 Python 加密时可能会有两种形式,一种是对python转成的exe进行 保护,另一种是直接对.py或者.pyc文件进行保护,下面将列举两种形式的保护流程. ...
- javascript篇-知道value值,返回对象中的key值
前提是,value值是唯一的,业务中有这样一个需求,代码如下:
- 实例讲解TP5中关联模型
https://blog.csdn.net/github_37512301/article/details/75675054 一.关联模型在关系型数据库中,表之间有一对一.一对多.多对多的关系.在 T ...
- request.getSession(true)和request.getSession(false)的区别
request.getSession(true)和request.getSession(false)的区别 request.getSession(true):若存在会话则返回该会话,否则新建一个会 ...