zoukankan      html  css  js  c++  java
  • poj 2195Going Home解题报告

    链接:http://poj.org/problem?id=2195

    这道题是二分图的最佳匹配问题,而且属于最小匹配,km算法的模版题,题目保证了人数和房子数相等,这是自己第一道km算法题,刚开始对km算法不理解,看各种讲解,终于搞懂了其运行过程和能求出解的原因。km算法保证在整个算法的运行过程中对于匹配x,y保证lx[x]+ly[y]>=w(x,y);最终找到的是lx[x]+ly[y]=w(x,y)的解。

    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #define N 200
      5 #define inf 0x7fffffff
      6 using namespace std;
      7 struct point
      8 {
      9     int x,y;
     10 };
     11 point ph[N],pm[N];
     12 int lx[N],ly[N];
     13 int map[N][N];
     14 int match[N];
     15 int usedx[N],usedy[N],flag;
     16 char g[N][N];
     17 int abs(int a)
     18 {
     19     return a>=0?a:-a;
     20 }
     21 int max(int a,int b)
     22 {
     23     return a>b?a:b;
     24 }
     25 int min(int a,int b)
     26 {
     27     return a<b?a:b;
     28 }
     29 int h,m;
     30 void build()
     31 {
     32     int i,j;
     33     for(i=1;i<=h;i++)
     34     for(j=1;j<=m;j++)
     35     map[i][j]=abs(ph[i].x-pm[j].x)+abs(ph[i].y-pm[j].y);
     36 }
     37 bool dfs(int x)
     38 {
     39     int i,j,k;
     40     usedx[x]=flag;
     41     for(i=1;i<=m;i++)
     42     {
     43         if(usedy[i]!=flag&&lx[x]+ly[i]==map[x][i])
     44         {
     45             usedy[i]=flag;
     46             if(match[i]==-1||dfs(match[i]))
     47             {
     48                 match[i]=x;
     49                 return true;
     50             }
     51         }
     52     }
     53     return false;
     54 }
     55 int km()
     56 {
     57     memset(lx,127,sizeof(lx));
     58     memset(ly,0,sizeof(ly));
     59     build();
     60     flag=0;
     61     int res=0;
     62     int i,j,k,d;
     63     for(i=1;i<=h;i++)
     64     for(j=1;j<=m;j++)
     65     lx[i]=min(lx[i],map[i][j]);//最大权匹配就取最大值,最小权匹配就取最小值
     66     memset(match,-1,sizeof(match));
     67     for(i=1;i<=h;i++)
     68     {
     69         flag++;
     70         while(!dfs(i))
     71         {
     72             d=inf;
     73             for(j=1;j<=h;j++)
     74             {
     75                 if(usedx[j]==flag)
     76                 for(k=1;k<=m;k++)
     77                 if(usedy[k]!=flag)
     78                 d=min(map[j][k]-lx[j]-ly[k],d);
     79             }
     80             for(j=1;j<=h;j++)
     81             if(usedx[j]==flag)
     82             lx[j]+=d;
     83             for(j=1;j<=m;j++)
     84             {
     85                 if(usedy[j]==flag)
     86                 ly[j]-=d;
     87             }
     88             flag++;
     89         }
     90     }
     91     for(i=1;i<=m;i++)
     92     res+=map[match[i]][i];
     93     return res;
     94 }
     95 int main()
     96 {
     97     int r,c,i,j,k;
     98     char s;
     99     while(scanf("%d%d",&r,&c)&&(r||c))
    100     {
    101         h=m=0;
    102         for(i=1;i<=r;i++)
    103         scanf("%s",g[i]+1);
    104         for(i=1;i<=r;i++)//建图过程
    105         for(j=1;j<=c;j++)
    106         {
    107             if(g[i][j]=='H')
    108             {
    109                 ph[++h].x=i;
    110                 ph[h].y=j;
    111             }
    112             if(g[i][j]=='m')
    113             {
    114                 pm[++m].x=i;
    115                 pm[m].y=j;
    116             }
    117         }
    118         //printf("%d %d\n",h,m);
    119         printf("%d\n",km());
    120     }
    121     return 0;
    122 }
  • 相关阅读:
    FireFox浏览器的下载和安装、借助RamDisk让你的FireFox飞起来
    XXX is not in the sudoers file. This incident will be reported 的问题解决方案
    UVA How Big Is It?
    CentOS配置smaba与Windows共享文件
    博客说明
    linux 下安装jdk及配置jdk环境图解
    swift 笔记 (十二) —— 下标
    依据先中序序列或后中序序列确定二叉树
    opencv2使用形态学滤波对图像进行边缘及角点检測
    $POST 、$HTTP_RAW_POST_DATA、php://input三者之间的差别
  • 原文地址:https://www.cnblogs.com/caozhenhai/p/2481205.html
Copyright © 2011-2022 走看看