zoukankan      html  css  js  c++  java
  • POJ 2195 Going Home(KM算法模板)

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

    题目大意:

    给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致。

    man每移动一格需花费$1(即单位费用=单位距离),一间house只能入住一个man。现在要求所有的man都入住house,求最小费用。

    解题思路:

    将每个man和house建边求最佳匹,KM模板。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=5e2+5;
    const int INF=0x3f3f3f3f;
    
    int ny,nx;
    int lx[N],ly[N],link[N],slack[N],g[N][N];
    bool visx[N],visy[N];
    
    struct node{
        int x,y;
        node(){}
        node(int x,int y):x(x),y(y){}
    }a[N],b[N];
    
    bool dfs(int x){
        visx[x]=true;
        for(int y=0;y<ny;y++){
            if(visy[y]) continue;
            int tmp=lx[x]+ly[y]-g[x][y];
            if(tmp==0){
                visy[y]=true;
                if(link[y]==-1||dfs(link[y])){
                    link[y]=x;
                    return true;
                }
            }
            else if(slack[y]>tmp)
                slack[y]=tmp;
        }
        return false;
    }
    
    int KM(){
        memset(link,-1,sizeof(link));
        memset(ly,0,sizeof(ly));
        for(int i=0;i<nx;i++){
            lx[i]=-INF;
            for(int j=0;j<ny;j++){
                if(g[i][j]>lx[i])
                    lx[i]=g[i][j];
            }
        }
        for(int x=0;x<nx;x++){
            for(int i=0;i<ny;i++){
                slack[i]=INF;
            }
            while(true){
                memset(visx,false,sizeof(visx));
                memset(visy,false,sizeof(visy));
                if(dfs(x)) break;
                int d=INF;
                for(int i=0;i<ny;i++){
                    if(!visy[i]&&slack[i]<d)
                        d=slack[i];
                }
                for(int i=0;i<nx;i++){
                    if(visx[i])
                        lx[i]-=d;
                }
                for(int i=0;i<ny;i++){
                    if(visy[i])
                        ly[i]+=d;
                }
            }
        }
        int ans=0;
        for(int i=0;i<ny;i++){
            if(link[i]!=-1)
                ans+=g[link[i]][i];
        }
        return ans;
    }
    
    
    int main(){
        int n,m;
        while(~scanf("%d%d",&n,&m)){
            if(n==0&&m==0) break;
            nx=ny=0;
            char str[N];
            for(int i=0;i<n;i++){
                scanf("%s",str);
                for(int j=0;j<m;j++){
                    if(str[j]=='m'){
                        a[nx++]=node(i,j);
                    }
                    else if(str[j]=='H'){
                        b[ny++]=node(i,j);
                    }
                }
            }
            for(int i=0;i<nx;i++){
                for(int j=0;j<ny;j++){
                    g[i][j]=-(abs(a[i].x-b[j].x)+abs(a[i].y-b[j].y));
                }
            }
            printf("%d
    ",-KM());
        }
        return 0;
    }
  • 相关阅读:
    坚持的力量 第一篇
    有声似无声
    坚持的力量
    新浪技术面试题
    单词的个数
    我的研究生规划
    go to the train station
    百度面试题求绝对值最小的数
    关于CIW认证考试CIW 常见问题解答
    [恢]hdu 2087
  • 原文地址:https://www.cnblogs.com/fu3638/p/8785850.html
Copyright © 2011-2022 走看看