HDU-1533 Going Home
来源:互联网 发布:雀圣软件官方 编辑:程序博客网 时间:2024/05/16 17:48
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1533
题目大意:
给你一个N行M列的矩阵,其中“.”代表空地,“H”代表房子,“m”代表人,其中有n个房子和n个人。现在要求每个人进入一间房子,且人走一步需要支付1美元。
求最小需要花费多少美元才能让所有人都进入到房子中(每个人只能进入一间房子,每个房子只能容纳一个人)。
解题思路:
这道题其实就是二分图最优匹配的变形而已。
因为要求的其实是最小权值之和。而KM算法求的是最大权值之和。
为此,我们可以有两种方法来解决:
1.在建图的时候,将每条边的权值变为负数。然后lx[i]初始化为-INT_MAX,结果输出-ans,就可以得到最小权值。
2.在建图的时候,用一个相对的大数减去每个权值,比如现在边为6,8,10.我用100来减,得到的边为94,92,90.最后输出时,用100*n-ans也可以得到最小的权值。
方法1代码如下:
#include<iostream>#include<cstring>#include<climits>#include<cstdio>#include<algorithm>using namespace std;#define N 110char maps[N][N];int map[N][N];int lx[N], ly[N];int slack[N];int match[N];bool visitx[N], visity[N];int n;bool Hungary(int u){visitx[u] = true;for(int i = 0; i < n; ++i){if(visity[i])continue;else{if(lx[u] + ly[i] == map[u][i]){visity[i] = true;if(match[i] == -1 || Hungary(match[i])){match[i] = u;return true;}}elseslack[i] = min(slack[i], lx[u] + ly[i] - map[u][i]);}}return false;}void KM_perfect_match(){int temp;for(int i = 0; i < n; ++i) //初始化大负数lx[i] = -INT_MAX;memset(ly, 0, sizeof(ly));for(int i = 0; i < n; ++i)for(int j = 0; j < n; ++j)lx[i] = max(lx[i], map[i][j]);for(int i = 0; i < n; ++i){for(int j = 0; j < n; ++j)slack[j] = INT_MAX;while(1){memset(visitx, false, sizeof(visitx));memset(visity, false, sizeof(visity));if(Hungary(i))break;else{temp = INT_MAX;for(int j = 0; j < n; ++j)if(!visity[j])temp = min(temp, slack[j]);for(int j = 0; j < n; ++j){if(visitx[j])lx[j] -= temp;if(visity[j])ly[j] += temp;elseslack[j] -= temp;}}}}}int main(){int row, col, ans, numi, numj;while(scanf("%d%d", &row, &col) && (row + col)){n = ans = numi = numj = 0;memset(match, -1, sizeof(match));for(int i = 0; i < row; ++i){scanf("%*c");for(int j = 0; j < col; ++j){scanf("%c", &maps[i][j]);if(maps[i][j] == 'm')n++;}}for(int i = 0; i < row; ++i) //建图{for(int j = 0; j < col; ++j){if(maps[i][j] == 'm'){for(int k = 0; k < row; ++k){for(int l = 0; l < col; ++l){if(maps[k][l] == 'H')map[numi][numj++] = - (abs(k - i) + abs(l - j)); //变为负权边}}numi++;numj = 0;}}}KM_perfect_match();for(int i = 0; i < n; ++i)ans += map[match[i]][i];printf("%d\n", - ans); //结果取反}return 0;}方法2代码如下:
#include<iostream>#include<cstring>#include<climits>#include<cstdio>#include<algorithm>using namespace std;#define N 110char maps[N][N];int map[N][N];int lx[N], ly[N];int slack[N];int match[N];bool visitx[N], visity[N];int n;bool Hungary(int u){visitx[u] = true;for(int i = 0; i < n; ++i){if(visity[i])continue;else{if(lx[u] + ly[i] == map[u][i]){visity[i] = true;if(match[i] == -1 || Hungary(match[i])){match[i] = u;return true;}}elseslack[i] = min(slack[i], lx[u] + ly[i] - map[u][i]);}}return false;}void KM_perfect_match(){int temp;memset(lx, 0, sizeof(lx));memset(ly, 0, sizeof(ly));for(int i = 0; i < n; ++i)for(int j = 0; j < n; ++j)lx[i] = max(lx[i], map[i][j]);for(int i = 0; i < n; ++i){for(int j = 0; j < n; ++j)slack[j] = INT_MAX;while(1){memset(visitx, false, sizeof(visitx));memset(visity, false, sizeof(visity));if(Hungary(i))break;else{temp = INT_MAX;for(int j = 0; j < n; ++j)if(!visity[j])temp = min(temp, slack[j]);for(int j = 0; j < n; ++j){if(visitx[j])lx[j] -= temp;if(visity[j])ly[j] += temp;elseslack[j] -= temp;}}}}}int main(){int row, col, ans, numi, numj;while(scanf("%d%d", &row, &col) && (row + col)){n = ans = numi = numj = 0;memset(match, -1, sizeof(match));for(int i = 0; i < row; ++i){scanf("%*c");for(int j = 0; j < col; ++j){scanf("%c", &maps[i][j]);if(maps[i][j] == 'm')n++;}}for(int i = 0; i < row; ++i) //建图{for(int j = 0; j < col; ++j){if(maps[i][j] == 'm'){for(int k = 0; k < row; ++k){for(int l = 0; l < col; ++l){if(maps[k][l] == 'H')map[numi][numj++] = 100 - (abs(k - i) + abs(l - j)); //大数减边}}numi++;numj = 0;}}}KM_perfect_match();for(int i = 0; i < n; ++i)ans += map[match[i]][i];printf("%d\n", 100 * n - ans); }return 0;}
- HDU-1533 Going Home
- HDU 1533 Going Home
- HDU 1533 Going Home
- HDU 1533 Going Home
- hdu 1533 Going Home
- hdu 1533 Going Home
- HDU 1533 Going Home
- hdu acm 1533 Going Home
- HDU 1533 Going Home (KM)
- hdu 1533 Going Home (KM裸题)
- hdu(1533)Going Home(poj2195)
- hdu 1533 Going Home(二分图)
- POJ 2195 & hdu 1533 Going Home
- HDU--1533--Going Home--KM算法
- hdu 1533 Going Home 最小费用流
- hdu 1533 Going Home (KM算法)
- HDU 1533 Going Home【km应用】
- hdu 1533 Going Home(KM)
- OpenGL模型视图变换、投影变换、视口变换
- enyo学习笔记1
- 动态扩大数组
- 【巴蜀模拟试题】:L语言(difficult)
- android 类似QQ 换皮肤 实现思路 apk资源共享
- HDU-1533 Going Home
- va_start va_end 的使用和原理
- 程序员的十层楼:大家都来测测你的技术层级
- 函数编写规范
- 可重入函数
- Linux 内核编译详解
- Eclipse总出这个错误You must restart adb and Eclipse
- 详解_C语言可变参数_va_list和_vsnprintf及printf实现
- Android中Android.mk文件的使用