zoukankan      html  css  js  c++  java
  • hdu 1533(最小权匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1533

    题意:

    给你一个N行M列的矩阵,其中“.”代表空地,“H”代表房子,“m”代表人,其中有n个房子和n个人。现在要求每个人进入一间房子,且人走一步需要支付1美元。

    求最小需要花费多少美元才能让所有人都进入到房子中(每个人只能进入一间房子,每个房子只能容纳一个人)。

    思路:就是一个二分图最优匹配的变形,所以说建图很重要啊!!!(把‘m'的坐标计入到X集,’H‘的坐标计入到Y集)在建图的时候,将每条边的权值变为负数。然后lx[i]初始化为-inf,结果输出-ans,就可以得到最小权值

    View Code
      1 #include<iostream>
      2 const int MAXN=110;
      3 const int inf=1<<30;
      4 using namespace std;
      5 char G[MAXN][MAXN];
      6 int map[MAXN][MAXN];
      7 int lx[MAXN],ly[MAXN];
      8 int match[MAXN];
      9 bool visitx[MAXN],visity[MAXN];
     10 int n;
     11 
     12 int Hungary(int u){
     13     visitx[u]=true;
     14     for(int i=0;i<n;i++){
     15         if(!visity[i]&&lx[u]+ly[i]==map[u][i]){
     16             visity[i]=true;
     17             if(match[i]==-1||Hungary(match[i])){
     18                 match[i]=u;
     19                 return true;
     20             }
     21         }
     22     }
     23     return false;
     24 }
     25 
     26 void KM_prefect_match(){
     27     int tmp;
     28     //注意,此时要初始化为无穷小
     29     for(int i=0;i<n;i++){
     30         lx[i]=-inf;
     31     }
     32     memset(ly,0,sizeof(ly));
     33     for(int i=0;i<n;i++){
     34         for(int j=0;j<n;j++){
     35             lx[i]=max(lx[i],map[i][j]);
     36         }
     37     }
     38     for(int i=0;i<n;i++)
     39     {
     40         while(1){
     41             memset(visitx,false,sizeof(visitx));
     42             memset(visity,false,sizeof(visity));
     43             if(Hungary(i))//匹配成功
     44                 break;
     45             else {
     46                 tmp=inf;
     47                 for(int j=0;j<n;j++)if(visitx[j]){//x在交错树中
     48                     for(int k=0;k<n;k++){
     49                         //y在交错树外
     50                         if(!visity[k]&&tmp>lx[j]+ly[k]-map[j][k]){
     51                             tmp=lx[j]+ly[k]-map[j][k];
     52                         }
     53                     }
     54                 }
     55                 //更新顶标
     56                 for(int j=0;j<n;j++){
     57                     if(visitx[j])
     58                         lx[j]-=tmp;
     59                     if(visity[j])
     60                         ly[j]+=tmp;
     61                 }
     62             }
     63         }
     64     }
     65 }
     66 
     67 int main(){
     68     int row,col;
     69     while(~scanf("%d%d",&row,&col)){
     70         if(row==0&&col==0)break;
     71         n=0;
     72         int cnt1=0,cnt2=0;
     73         memset(map,0,sizeof(map));
     74         memset(match,-1,sizeof(match));
     75         for(int i=0;i<row;i++){
     76             scanf("%s",G[i]);
     77             for(int j=0;j<col;j++){
     78                 if(G[i][j]=='m')n++;
     79             }
     80         }
     81         //建图很重要!!!
     82         for(int i=0;i<row;i++){
     83             for(int j=0;j<col;j++){
     84                 if(G[i][j]=='m'){
     85                     for(int k=0;k<row;k++){
     86                         for(int l=0;l<col;l++){
     87                             if(G[k][l]=='H'){
     88                                 map[cnt1][cnt2++]=-1*(abs(i-k)+abs(j-l));//由于求得是最小权值和,取相反数
     89                             }
     90                         }
     91                     }
     92                     cnt1++;
     93                     cnt2=0;
     94                 }
     95             }
     96         }
     97         KM_prefect_match();
     98         int ans=0;
     99         for(int i=0;i<n;i++){
    100             ans+=map[match[i]][i];
    101         }
    102         printf("%d\n",-ans);//最后取相反数就行了
    103     }
    104     return 0;
    105 }
  • 相关阅读:
    《设计模式》(精华集)
    TClientDataSet使用(二)
    害我查了半天的错误!av错误,小心Component对象使用Application当Owner
    释放自己
    最近在转C#
    TClientDataSet的使用技巧
    小心使用可修改的常量。
    指数函数和正弦函数相乘
    adb 常用命令
    win7下ie9设置无法保存的问题
  • 原文地址:https://www.cnblogs.com/wally/p/2996177.html
Copyright © 2011-2022 走看看