zoukankan      html  css  js  c++  java
  • 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
    ", KM());
    126     }
    127     return 0;
    128 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    7-6
    7-5
    7-3
    7-4
    ios中怎样在本类中调用drawRect方法
    ios中怎么样判断路径最后的后缀名称
    ios中怎么样转行大小写
    ios中怎么样自动剪切图片周围超出的部分
    ios中如何计算(页数,行数,等等的算法)
    IOS中 如何去除Tabview里面cell之间的下划线
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4479780.html
Copyright © 2011-2022 走看看