uva 1045(二分图最大权匹配)
2014-02-25 20:56
525 查看
题意:n*n的棋盘上有n枚棋子。现在要让你以最小的步数把棋盘分隔开(可以是横竖着的五个一排, 也可以是两个对角线)。问你最小步数
思路:首先枚举各个最终状态起始状态与最终状态建边权值为花费的负数,然后求最大权匹配去一下最大值。最后答案再取相反数。
代码如下:
View Code
思路:首先枚举各个最终状态起始状态与最终状态建边权值为花费的负数,然后求最大权匹配去一下最大值。最后答案再取相反数。
代码如下:
/************************************************** * Author : xiaohao Z * Blog : http://www.cnblogs.com/shu-xiaohao/ * Last modified : 2014-02-25 19:54 * Filename : uva_1045.cpp * Description : * ************************************************/ #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <queue> #include <stack> #include <vector> #include <set> #include <map> #define MP(a, b) make_pair(a, b) #define PB(a) push_back(a) using namespace std; typedef long long ll; typedef pair<int, int> pii; typedef pair<unsigned int,unsigned int> puu; typedef pair<int, double> pid; typedef pair<ll, int> pli; typedef pair<int, ll> pil; const int INF = 0x3f3f3f3f; const double eps = 1E-6; const int LEN = 101; int nx, ny, Map[LEN][LEN], n; int link[LEN], lx[LEN], ly[LEN], slack[LEN], visx[LEN], visy[LEN]; struct P{int x, y;}p[LEN]; //template from kuangbin int dfs(int x){ visx[x] = 1; for(int y=0; y<ny; y++){ if(visy[y]) continue; int tmp = lx[x] + ly[y] - Map[x][y]; if(!tmp){ visy[y] = 1; if(link[y] < 0 || dfs(link[y])){ link[y] = x; return true; } }else if(slack[y] > tmp) slack[y] = tmp; } return false; } int KM(){ memset(link, -1, sizeof link); memset(ly, 0, sizeof ly); for(int i=0; i<nx; i++){ lx[i] = -INF; for(int j=0; j<ny; j++) if(Map[i][j] > lx[i]) lx[i] = Map[i][j]; } for(int x=0; x<nx; x++){ for(int i=0; i<ny; i++) slack[i] = INF; while(true){ memset(visx, 0, sizeof visx); memset(visy, 0, sizeof visy); if(dfs(x)) break; int d = INF; for(int i=0; i<ny; i++) if(!visy[i] && d > slack[i]) d = slack[i]; for(int i=0; i<nx; i++) if(visx[i]) lx[i] -= d; for(int i=0; i<ny; i++){ if(visy[i]) ly[i] += d; else slack[i] -= d; } } } int ret = 0; for(int i=0; i<ny; i++) if(link[i] != -1) ret += Map[link[i]][i]; return ret; } inline int dis(int a, int b, int c, int d){return abs(a-c) + abs(b-d);} int main() { // freopen("in.txt", "r", stdin); int kase = 1; while(scanf("%d", &n)!=EOF && n){ nx = ny = n; for(int i=0; i<n; i++){ scanf("%d%d", &p[i].x, &p[i].y); p[i].x--;p[i].y--; } int ans = -INF; //row for(int i=0; i<n; i++){ memset(Map, 0x3f, sizeof Map); for(int j=0; j<n; j++) for(int k=0; k<n; k++){ Map[j][k] = -dis(p[j].x, p[j].y, i, k); } ans = max(ans, KM()); } //col for(int i=0; i<n; i++){ memset(Map, 0x3f, sizeof Map); for(int j=0; j<n; j++) for(int k=0; k<n; k++) Map[j][k] = -dis(p[j].x, p[j].y, k, i); ans = max(ans, KM()); } // memset(Map, 0x3f, sizeof Map); for(int i=0; i<n; i++) for(int j=0; j<n; j++){ Map[i][j] = -dis(p[i].x, p[i].y, j, j); } ans = max(ans, KM()); memset(Map, 0x3f, sizeof Map); for(int i=0; i<n; i++) for(int j=0; j<n; j++) Map[i][j] = -dis(p[i].x, p[i].y, j, n-j-1); ans = max(ans, KM()); ans = -ans; printf("Board %d: %d moves required.\n\n", kase++, ans); } return 0; }
View Code
相关文章推荐
- hadoop2.2.0的编译(64位linux系统)
- 如何删除”我的电脑“中的百度云管家图标
- 数据笔记3
- SQLServer 2008 (六) 基础总结
- 畅通工程续
- 打开中文网站显示英文或者在浏览页面查询时无结果显示出现乱码
- Linux操作系统下IPTables配置
- 不算java初学者,但依然薄弱的太多
- java线程系列---Runnable和Thread的区别 .
- POJ 2762 Going from u to v or from v to u? Tarjan缩点+判断链
- 【Linux C】时间和日历历程
- 如何显示文件后缀名(来源 百度)
- 安卓中遇到服务端json返回处理错误
- 空基类优化
- URAL 1152 False Mirrors 状压+记忆化搜索
- hibernate与mysql映射类型对应表与mysql导入导出
- java环境
- 在ListView上面动态显示控件
- 分类器是如何做检测的?——CascadeClassifier中的detectMultiScale函数解读
- 红黑树的插入删除-红黑树动态顺序统计