poj 2195 Going Home (km算法)
题目链接:
http://poj.org/problem?id=2195
解题思路:
把man和home都提取出来,然后算出每个man和home的距离算出来,然后建立匹配图,套用km算法的模板,求最小权值匹配,km模板一般是求最大权匹配,求最小的话,一般是取负,当然如果感觉取负逼格太low,也可以用下面的办法,改进模板。
代码:
1 //写的代码太菜,不懂建立匹配图的时候为什么下表从零开始就会使劲wa,但是改成1就会ac,有看出来的小伙伴们请大声说出来,跪谢!!!!! 2 //KM算法求完备匹配下的最小权匹配 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 #include <cmath> 8 using namespace std; 9 10 #define maxn 110 11 #define INF 0x3f3f3f3f 12 int map[maxn][maxn]/*匹配图*/; 13 int used[maxn]/*x与y的匹配值*/; 14 int s[maxn]/*修改量*/; 15 int n, m; 16 int lx[maxn], ly[maxn];/*顶标*/ 17 int visx[maxn], visy[maxn]; 18 19 struct node 20 { 21 int x, y; 22 void init(int xx, int yy) 23 { 24 x = xx; 25 y = yy; 26 } 27 }; 28 29 int Fas(int x, int y) 30 { 31 if (x > y) 32 return x - y; 33 return y - x; 34 } 35 int find (int x) 36 {//匈牙利算法,增广路经,扩大相等子图 37 visx[x] = 1; 38 for (int i=1; i<n; i++) 39 { 40 if (!visy[i] && lx[x]+ly[i] == map[x][i]) 41 { 42 visy[i] = 1; 43 if (!used[i] || find(used[i])) 44 { 45 used[i] = x; 46 return 1; 47 } 48 } 49 else 50 //s[i] = min (s[i], lx[x] + ly[i] - map[x][i]); 51 //最大权匹配 52 s[i] = min (s[i], map[x][i] - (lx[x] + ly[i]));//更新修改值,保证最小,使求得的结果最优 53 } 54 return 0; 55 } 56 int KM() 57 { 58 memset (used, 0, sizeof(used)); 59 memset (ly, 0, sizeof(ly)); 60 for (int i=1; i<n; i++)//初始化顶标 61 lx[i] = INF;//lx[i] = 0;最大权匹配 62 63 for (int i=1; i<n; i++) 64 for (int j=0; j<n; j++) 65 lx[i] = min(lx[i], map[i][j]); 66 67 for (int i=1; i<n; i++) 68 { 69 for (int j=1; j<n; j++) 70 s[j] = INF; 71 while (1) 72 { 73 memset (visx, 0, sizeof(visx)); 74 memset (visy, 0, sizeof(visy)); 75 76 if (find(i)) 77 break; 78 79 int num = INF; 80 for (int j=1; j<n; j++) 81 if (!visy[j])// 82 num = min (num, s[j]); 83 84 for (int j=1; j<n; j++) 85 { 86 if (visx[j]) 87 lx[j] += num;//lx[j] -= num;最大权匹配 88 if (visy[j]) 89 ly[j] -= num;//ly[j] += num;最大权匹配 90 else 91 s[j] -= num; 92 } 93 } 94 } 95 int res = 0; 96 for (int i=1; i<n; i++) 97 res += map[used[i]][i]; 98 return res; 99 100 } 101 int main () 102 { 103 char str[maxn]; 104 int a, b; 105 node home[maxn], man[maxn]; 106 while (scanf ("%d %d", &a, &b), a+b) 107 { 108 n = m = 1; 109 memset (map, 0, sizeof(map)); 110 111 for (int i=0; i<a; i++) 112 { 113 scanf ("%s", str); 114 for (int j=0; str[j]; j++) 115 { 116 if (str[j] == 'H') 117 home[n++].init(i, j); 118 if (str[j] == 'm') 119 man[m++].init(i, j); 120 } 121 } 122 for (int i=1; i<n; i++) 123 for (int j=1; j<m; j++) 124 map[i][j] = Fas(home[i].x , man[j].x) + Fas(home[i].y , man[j].y); 125 printf ("%d\n", KM()); 126 } 127 return 0; 128 }
本文为博主原创文章,未经博主允许不得转载。