UVA 10888 - Warehouse(二分图完美匹配)
UVA 10888 - Warehouse
题意:就是推箱子游戏,问最少要几步
思路:每一个箱子和目标位置建边。权值为负权值,然后进行二分图完美匹配就可以,注意不能到达的位置权值应该置为最小
代码:
- #include <cstdio>
- #include <cstring>
- #include <cmath>
- #include <algorithm>
- #include <queue>
- using namespace std;
- const int MAXNODE = 45;
- typedef int Type;
- const Type INF = 0x3f3f3f3f;
- struct KM {
- int n;
- Type g[MAXNODE][MAXNODE];
- Type Lx[MAXNODE], Ly[MAXNODE], slack[MAXNODE];
- int left[MAXNODE];
- bool S[MAXNODE], T[MAXNODE];
- void init(int n) {
- this->n = n;
- }
- void add_Edge(int u, int v, Type val) {
- g[u][v] = val;
- }
- bool dfs(int i) {
- S[i] = true;
- for (int j = 0; j < n; j++) {
- if (T[j]) continue;
- Type tmp = Lx[i] + Ly[j] - g[i][j];
- if (!tmp) {
- T[j] = true;
- if (left[j] == -1 || dfs(left[j])) {
- left[j] = i;
- return true;
- }
- } else slack[j] = min(slack[j], tmp);
- }
- return false;
- }
- void update() {
- Type a = INF;
- for (int i = 0; i < n; i++)
- if (!T[i]) a = min(a, slack[i]);
- for (int i = 0; i < n; i++) {
- if (S[i]) Lx[i] -= a;
- if (T[i]) Ly[i] += a;
- }
- }
- int km() {
- for (int i = 0; i < n; i++) {
- left[i] = -1;
- Lx[i] = -INF; Ly[i] = 0;
- for (int j = 0; j < n; j++)
- Lx[i] = max(Lx[i], g[i][j]);
- }
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < n; j++) slack[j] = INF;
- while (1) {
- for (int j = 0; j < n; j++) S[j] = T[j] = false;
- if (dfs(i)) break;
- else update();
- }
- }
- int ans = 0;
- for (int i = 0; i < n; i++)
- ans -= g[left[i]][i];
- return ans;
- }
- } gao;
- #define MP(a,b) make_pair(a,b)
- const int d[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
- typedef pair<int, int> pii;
- const int N = 45;
- int t, n, m;
- char g[N][N];
- int idb[N][N], idx[N][N], bn, xn, vis[N][N];
- pii tob[N], tox[N];
- int dis(pii a, pii b) {
- return abs(a.first - b.first) + abs(a.second - b.second);
- }
- void bfs(int xs, int ys) {
- queue<pii> Q;
- Q.push(MP(xs, ys));
- memset(vis, INF, sizeof(vis));
- vis[xs][ys] = 0;
- while (!Q.empty()) {
- pii u = Q.front();
- if (g[u.first][u.second] == 'X')
- gao.add_Edge(idb[xs][ys], idx[u.first][u.second], -vis[u.first][u.second]);
- Q.pop();
- for (int i = 0; i < 4; i++) {
- int x = u.first + d[i][0];
- int y = u.second + d[i][1];
- if (x < 0 || x >= n || y < 0 || y >= m || g[x][y] == '#') continue;
- if (vis[x][y] <= vis[u.first][u.second] + 1) continue;
- vis[x][y] = vis[u.first][u.second] + 1;
- Q.push(MP(x, y));
- }
- }
- }
- int main() {
- scanf("%d", &t);
- while (t--) {
- scanf("%d%d", &n, &m);
- bn = xn = 0;
- memset(gao.g, -INF, sizeof(gao.g));
- for (int i = 0; i < n; i++) {
- scanf("%s", g[i]);
- for (int j = 0; j < m; j++) {
- if (g[i][j] == 'B') {
- tob[bn] = MP(i, j);
- idb[i][j] = bn++;
- }
- if (g[i][j] == 'X') {
- tox[xn] = MP(i, j);
- idx[i][j] = xn++;
- }
- }
- }
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- if (g[i][j] == 'B') {
- bfs(i, j);
- }
- }
- }
- gao.init(bn);
- printf("%d\n", gao.km());
- }
- return 0;
- }
UVA 10888 - Warehouse(二分图完美匹配)的更多相关文章
- UVA 1411 - Ants(二分图完美匹配)
UVA 1411 - Ants 题目链接 题意:给定一些黑点白点,要求一个黑点连接一个白点,而且全部线段都不相交 思路:二分图完美匹配,权值存负的欧几里得距离,这种话,相交肯定比不相交权值小,所以做一 ...
- UVA 11383 - Golden Tiger Claw(二分图完美匹配扩展)
UVA 11383 - Golden Tiger Claw 题目链接 题意:给定每列和每行的和,给定一个矩阵,要求每一个格子(x, y)的值小于row(i) + col(j),求一种方案,而且全部行列 ...
- UVALive 4043 Ants(二分图完美匹配)
题意:每个蚁群有自己的食物源(苹果树),已知蚂蚁靠气味辨别行进方向,所以蚁群之间的行动轨迹不能重叠.现在给出坐标系中n个蚁群和n棵果树的坐标,两两配对,实现以上要求.输出的第 i 行表示第 i 个蚁群 ...
- UVA 11383 Golden Tiger Claw(最佳二分图完美匹配)
题意:在一个N*N的方格中,各有一个整数w(i,j),现在要求给每行构造row(i),给每列构造col(j),使得任意w(i,j)<=row(i)+col(j),输出row(i)与col(j)之 ...
- Hall定理 二分图完美匹配
充分性证明就先咕了,因为楼主太弱了,有一部分没看懂 霍尔定理内容 二分图G中的两部分顶点组成的集合分别为X, Y(假设有\(\lvert X \rvert \leq \lvert Y \rvert\) ...
- HDU2255 奔小康赚大钱 【模板】 二分图完美匹配
基本概念 二分图有两个种点:X和Y.X与Y之间存在一些边,每个边有一个权值.现要求求一组X与Y间的通过边实现的一一匹配,使得得到的边权和最大. 总体过程 对每个X节点设置一个顶标Xl,初值为与X相邻的 ...
- KM算法【带权二分图完美匹配】
先orz litble--KM算法 为什么要用KM算法 因为有的题丧心病狂卡费用流 KM算法相比于费用流来说,具有更高的效率. 算法流程 我们给每一个点设一个期望值[可行顶标] 对于左边的点来说,就是 ...
- Vasya and Endless Credits CodeForces - 1107F (二分图完美匹配)
大意: n中贷款, 每种只能买一次, 第$i$种给$a_i$元, 要还款$k_i$个月, 每个月底还$b_i$元. 每个月可以在月初申请一种贷. 求某一时刻能得到的最大钱数.
- UVa 1349 - Optimal Bus Route Design(二分图最佳完美匹配)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
随机推荐
- node post和get请求原理
重要:GET和POST请求他们都是上行请求,都是把数据从浏览器带向服务器的方式, GET 请求实际上就是识别URL中的querystring部分POST请求,一般用来发送大量的内容,此时node非常害 ...
- 数据库 'tempdb' 的事务日志已满。若要查明无法重用日志中的空间的原因
最常的做法: --1.清空日志 DUMP TRANSACTION tempdb WITH NO_LOG --2.截断事务日志: BACKUP LOG tempdb WITH NO_LOG --3.收缩 ...
- 【Oracle】DG三种保护模式及切换方式
一.三种保护方式 Required Redo Transport Attributes for Data Protection Modes Maximum Availability Maximum P ...
- JAVA软件工程师应该具备哪些基本素质?
必知:软件企业要求基础软件工程师具备六大基本素质,即良好的编码能力.自觉的规范意识和团队精神.认识和运用数据库的能力.较强的英语阅读和写作能力.具有软件工程的概念和求知欲和进取心. 1.良好的编码能力 ...
- AI:IPPR的模式生成-学习/训练方式(基本结构)
前言: 一个完备的模式识别系统,必然包含一个模式识别模型,此外还要附加一个评价模型,以及为了构建识别模型而构建的学习模型,并选择在学习模型中使用的学习方法. 否则 w=w 这样,)那样 ...
- OpenCV:OpenCV图像旋转的代码
OpenCV图像旋转的代码 cv::transpose( bfM, bfM ) 前提:使用两个矩阵Mat型进行下标操作是不行的,耗费的时间太长了.直接使用两个指针对拷贝才是王道.不知道和OpenCV比 ...
- 通用功能类:改变WinForm窗体显示颜色
一.显示窗体调用方法 protected override void OnLoad(EventArgs e) { MDIClientSupport.SetBevel ...
- css单双行样式
#random_box li:nth-child(odd) {//双行 background: #fff5c4; } #random_box li:nth-child(even) {//单行 back ...
- java 发送http请求
参考别人的 package test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputS ...
- 博弈论题目总结(二)——SG组合游戏及变形
SG函数 为了更一般化博弈问题,我们引入SG函数 SG函数有如下性质: 1.如果某个状态SG函数值为0,则它后继的每个状态SG函数值都不为0 2.如果某个状态SG函数值不为0,则它至少存在一个后继的状 ...