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 }
  • 相关阅读:
    310. Minimum Height Trees -- 找出无向图中以哪些节点为根,树的深度最小
    297. Serialize and Deserialize Binary Tree *HARD*
    235.236. Lowest Common Ancestor of a Binary (Search) Tree -- 最近公共祖先
    222. Count Complete Tree Nodes -- 求完全二叉树节点个数
    208. Implement Trie (Prefix Tree) -- 键树
    excel函数累加求和与累计百分比应用
    js去除空格
    js获取标签下标
    js中对String去空格
    css的三种使用方式:行内样式,内嵌样式,外部引用样式
  • 原文地址:https://www.cnblogs.com/huangxf/p/4331400.html
Copyright © 2011-2022 走看看