zoukankan      html  css  js  c++  java
  • hdu 1533 Going Home 最小费用最大流

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

    On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every step he moves, until he enters a house. The task is complicated with the restriction that each house can accommodate only one little man.

    Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates there is a little man on that point. 

    You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.

    题意描述:在n*m的矩阵格子里有x个人要走到x个房间里,每个房间里只能放一人,人在目前所在的格子处向上下左右相邻的格子走一步就花费1美元,问最后全部的人走到房间后最小的花费。

    算法分析:这道题可以用KM算法或者最小费用最大流算法解之,这里讲解一下最小费用最大流的方法。

    新增源点from和汇点to,from->人(w为1,cost为0)

    房子->to(w为1,cost为0)

    每个人->每间房(w为1,cost为最短路径的美元花费)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<vector>
      8 #include<queue>
      9 #define inf 0x7fffffff
     10 using namespace std;
     11 const int maxn=10000+100;
     12 const int M = 40000+100;
     13 
     14 int n,m,from,to;
     15 struct node
     16 {
     17     int v,flow,cost;
     18     int next;
     19 }edge[M*4];
     20 int head[maxn],edgenum;
     21 int dis[maxn],pre[maxn],pid[maxn],vis[maxn];
     22 
     23 void add(int u,int v,int flow,int cost)
     24 {
     25     edge[edgenum].v=v ;edge[edgenum].flow=flow ;
     26     edge[edgenum].cost=cost ;edge[edgenum].next=head[u];
     27     head[u]=edgenum++;
     28 
     29     edge[edgenum].v=u ;edge[edgenum].flow=0;
     30     edge[edgenum].cost=-cost ;edge[edgenum].next=head[v];
     31     head[v]=edgenum++;
     32 }
     33 
     34 int spfa()
     35 {
     36     for (int i=1 ;i<=to ;i++)
     37     {
     38         dis[i]=inf;
     39         vis[i]=0;
     40     }
     41     queue<int> Q;
     42     Q.push(from);
     43     dis[from]=0;
     44     vis[from]=1;
     45     while (!Q.empty())
     46     {
     47         int u=Q.front() ;Q.pop() ;
     48         vis[u]=0;
     49         for (int i=head[u] ;i!=-1 ;i=edge[i].next)
     50         {
     51             int v=edge[i].v;
     52             if (edge[i].flow>0 && dis[v]>dis[u]+edge[i].cost)
     53             {
     54                 dis[v]=dis[u]+edge[i].cost;
     55                 pre[v]=u;
     56                 pid[v]=i;
     57                 if (!vis[v])
     58                 {
     59                     vis[v]=1;
     60                     Q.push(v);
     61                 }
     62             }
     63         }
     64     }
     65     return dis[to];
     66 }
     67 
     68 int mincost()
     69 {
     70     int aug=0,maxflow=0;
     71     int ans=0,tmp=0;
     72     while (1)
     73     {
     74         tmp=spfa();
     75         if (tmp==inf) break;
     76         aug=inf;
     77         for (int i=to ;i!=from ;i=pre[i])
     78         {
     79             if (edge[pid[i] ].flow<aug)
     80                 aug=edge[pid[i] ].flow;
     81         }
     82         for (int i=to ;i!=from ;i=pre[i])
     83         {
     84             edge[pid[i] ].flow -= aug;
     85             edge[pid[i]^1 ].flow += aug;
     86         }
     87         maxflow += aug;
     88         ans += tmp;
     89     }
     90     return ans;
     91 }
     92 
     93 int main()
     94 {
     95     while (scanf("%d%d",&n,&m)!=EOF)
     96     {
     97         if (!n && !m) break;
     98         memset(head,-1,sizeof(head));
     99         edgenum=0;
    100         char str[111][111];
    101         memset(str,0,sizeof(str));
    102         for (int i=1 ;i<=n ;i++)
    103         {
    104             scanf("%s",str[i]+1);
    105         }
    106         from=n*m+1;
    107         to=from+1;
    108         int h[111],c[111],cnt=0;
    109         int h2[111],c2[111],cnt2=0;
    110         for (int i=1 ;i<=n ;i++)
    111         {
    112             for (int j=1 ;j<=m ;j++)
    113             {
    114                 if (str[i][j]=='m')
    115                 {
    116                     add(from,(i-1)*m+j,1,0);
    117                     h[cnt]=i ;c[cnt]=j ;cnt++ ;
    118                 }
    119                 else if (str[i][j]=='H')
    120                 {
    121                     add((i-1)*m+j,to,1,0);
    122                     h2[cnt2]=i ;c2[cnt2]=j ;cnt2++ ;
    123                 }
    124             }
    125         }
    126         for (int i=0 ;i<cnt ;i++)
    127         {
    128             for (int j=0 ;j<cnt2 ;j++)
    129                 add((h[i]-1)*m+c[i],(h2[j]-1)*m+c2[j],1,abs(h[i]-h2[j])+abs(c[i]-c2[j]));
    130         }
    131         printf("%d
    ",mincost());
    132     }
    133     return 0;
    134 }
  • 相关阅读:
    web前端node.js常用命令
    常见的一部份面试题
    JavaScript基础语法
    表单属性、标签
    文字美化学习总结
    JS-实现横向手风琴
    Js-带进度条的轮播图
    canvas-八卦图和时钟实现
    JS-闭包练习
    JS-上下文练习
  • 原文地址:https://www.cnblogs.com/huangxf/p/4331400.html
Copyright © 2011-2022 走看看