poj2054,poj2155

  poj2054,poj2155

  描述

  在网格地图上有n个小人和n栋房子。在单位时间内,每个小人都可以水平或垂直地移动一个单位步长到相邻的点。对于每个小人,你需要为他移动的每一步支付一美元的旅行费用,直到他进入一所房子。这项任务很复杂,因为每栋房子只能容纳一个小人。

  你的任务是计算把这n个小人送进那n个不同的房子你需要支付的最少的钱。输入是场景的映射,一个"."意味着一个空的空间,一个" H "代表那个点上的房子,一个" m "表示那个点上有一个小人。

  你可以把网格地图上的每一个点想象成一个相当大的正方形,那么它可以同时容纳n个小人;此外,如果一个小个子男人踩在一个有房子的格子上,而没有进入那个房子,那也没关系。

  投入

  输入中有一个或多个测试用例。每种情况都从给出两个整数普通和M的一行开始,其中普通是地图的行数,M是列数。其余的输入将是描述地图的普通行。你可以假设普通和M都在2到100之间,包括2和100。地图上会有相同数量的H和m;最多会有100栋房子。对于普通和m,输入将以0 0终止。

  输出

  对于每个测试用例,输出一行单整数,这是您需要支付的最小金额,以美元为单位。

  样本值输入

  2 2

  殿下.m

  .

  .

  .

  毫米.H

  .H.

  .H.

  .H.

  mmmHmmmm

  .H.

  .H.

  .H.

  抽样输出

  2

  来源

  太平洋西北2004

  考察点:最小费用最大流

  #包含标准视频

  #包含字符串。h

  #包含数学。h

  结构编号

  int x,y;

  }h[200],m[200];

  int cost[300][300],cap[300][300];

  int queue[1000000],status[300],dis[300],pre[300];

  int INF=0x7fffffff,sta,end

  int main()

  int EK();

  int i,j,n,u,s,t,top1,top2,x1,y1,x2,y2;

  char c;

  while(scanf(%d %d%*c ,n,u)!=EOF)

  如果(n==0 u==0)

  打破;

  top 1=top 2=0;

  for(I=1;我我)

  for(j=1;j j)

  scanf(%c ,

  if(c==H )

  h[top1].x=I;

  h[top1 ].y=j;

  }else if(c==m )

  m【top 2】x=I;

  m【top 2】y=j;

  getchar();

  if(top1==0)

  printf( 0 \ n );

  继续;

  memset(cap,0,sizeof(cap));

  记忆集(成本,0,sizeof(成本));

  n=top1

  for(I=1;我我)

  cap[0][I]=1;

  for(I=1;我我)

  x1=m[i-1].x;y1=m[i-1].y;

  for(j=1;j j)

  x2=h[j-1].x;y2=h[j-1]。y;

  x2=x2-x1;

  如果(x2 0)

  x2=-x2;

  y2=y2-y1;

  如果(y2 0)

  y2=-y2;

  cap[I][n j]=1;

  cost[I][n j]=(x2 y2);

  cost[n j][I]=-(x2 y2);

  for(I=1;我我)

  cap[n I][n n 1]=1;

  s=0;

  sta=0;end=2 * n ^ 1;

  s=EK();

  printf(%d\n ,s);

  返回0;

  int bfs()

  int i,j,base,top,x;

  base=top=0;

  for(I=0;我=结束;我)

  dis[I]=INF;

  记忆集(状态,0,sizeof(状态));

  queue[top]=0;

  状态[0]=1;

  dis[0]=0;

  而(底部顶部)

  x=queue[base];

  状态[x]=0;

  for(I=1;我=结束;我)

  如果(x!=i cap[x][i])

  if(dis[i] (dis[x] cost[x][i]))

  dis[I]=dis[x]cost[x][I];

  pre[I]=x;

  如果(!状态[我])

  状态[I]=1;

  queue[top]=I;

  if(dis[end]==INF)

  返回0;

  }否则

  返回1;

  int EK()

  int i,j,s=0,k,min=INF

  while(1)

  k=bfs();

  如果(k==0)

  打破;

  for(I=end;我!=0;i=pre[i])

  j=pre[I];

  if(min cap[j][i])

  min=cap[j][I];

  for(I=end;我!=0;i=pre[i])

  j=pre[I];

  s=(cost[j][I]* min);

  cap[j][I]-=min;

  cap[I][j]=min;

  返回s;

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: