hdu1533 Going Home (km Best Match algorithm for minimum weight)

analysis:

km algorithm is seeking the maximum weight
at the time of the construction of the diagram opposite number to take the weight
maximum weight is to find out the number of minimum weight opposite
the output of opposite number to

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=105;
struct Node{
    int x,y;
}a[maxm],b[maxm];//保存坐标
int l[maxm],r[maxm];//两边的期望值
int g[maxm][maxm];//权值
int lmark[maxm];//标记
int rmark[maxm];//标记
int need[maxm];//右半边还差多少能够被匹配
int now[maxm];//当前匹配
int acnt;//左半边数量
int bcnt;//右半边数量
int n,m;
int dfs(int x){
    lmark[x]=1;
    for(int i=1;i<=bcnt;i++){
        if(rmark[i])continue;
        int t=l[x]+r[i]-g[x][i];
        if(t==0){
            rmark[i]=1;
            if(now[i]==-1||dfs(now[i])){
                now[i]=x;
                return 1;
            }
        }else{
            need[i]=min(need[i],t);
        }
    }
    return 0;
}
int km(){
    memset(now,-1,sizeof now);
    memset(r,0,sizeof r);
    for(int i=1;i<=acnt;i++){
        l[i]=g[i][1];
        for(int j=2;j<=bcnt;j++){
            l[i]=max(l[i],g[i][j]);
        }
    }
    for(int i=1;i<=acnt;i++){
        for(int j=1;j<=bcnt;j++){
            need[j]=inf;
        }
        while(1){
            memset(lmark,0,sizeof lmark);
            memset(rmark,0,sizeof rmark);
            if(dfs(i))break;
            int d=inf;
            for(int j=1;j<=bcnt;j++){
                if(!rmark[j])d=min(d,need[j]);
            }
            for(int j=1;j<=acnt;j++){
                if(lmark[j])l[j]-=d;
            }
            for(int j=1;j<=bcnt;j++){
                if(rmark[j])r[j]+=d;
                else need[j]-=d;
            }
        }
    }
    int ans=0;
    for(int i=1;i<=bcnt;i++){
        ans+=g[now[i]][i];
    }
    return ans;
}
int getd(Node a,Node b){
    return abs(a.x-b.x)+abs(a.y-b.y);
}
int main(){
    while(cin>>n>>m&&(n+m)){
        acnt=0;
        bcnt=0;
        char t;
        getchar();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                t=getchar();//这题不需要存下整个图,只需要存有用的就行了
                if(t=='m'){
                    a[++acnt].x=i;
                    a[acnt].y=j;
                }else if(t=='H'){
                    b[++bcnt].x=i;
                    b[bcnt].y=j;
                }
            }
            getchar();
        }
        for(int i=1;i<=acnt;i++){
            for(int j=1;j<=bcnt;j++){
                g[i][j]=-getd(a[i],b[j]);//权值取相反数
            }
        }
        cout<<-km()<<endl;//输出相反数
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_44178736/article/details/93041680