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 }
  • 相关阅读:
    STM32使用keil串口输出中文乱码问题
    STM32CUBEMX忘记配置sys中的debug导致程序只能下载一次的问题
    远渡重洋的开源之路我是买家项目
    其实我就是个技术迷自身定位及展望
    五一上海行
    The Secret 秘密 读书笔记
    MySQL数据库设计复习笔记及项目实战
    PHP可调试团队开发环境配置支持企业级开发
    WIN7下QQ概念版使用手记
    Memento
  • 原文地址:https://www.cnblogs.com/huangxf/p/4331400.html
Copyright © 2011-2022 走看看