hdu(1533)Going Home(poj2195)

来源:互联网 发布:网络文明宣传语 编辑:程序博客网 时间:2024/06/05 16:47

对于本题,应用KM()算法计算最大权值,但因为要求花费最小,
则应将把人到房子的距离取负,其他的距离都是负无穷,则就
可以利用KM最后的结果再加上个负号。。
应注意的是,n是人的个数,再根据人的坐标,计算出每个人到
每个房子的距离存入map中。。

 

#include"stdio.h"
#include"string.h"
#include"math.h"
int map[1000][1000];
int sx[1000],sy[1000];
int lx[1000],ly[1000];
int link[1000],n;
#define inf 0x7fffffff
int find(int k)
{
 int i;
 sx[k]=1;
 for(i=0;i<n;i++)
 {
  if(sy[i]==0&&lx[k]+ly[i]==map[k][i])
  {
   sy[i]=1;
   if(link[i]==-1||find(link[i]))
   {
    link[i]=k;
    return 1;
   }
  }
 }
 return 0;
}
int KM()
{
 int i,j,k,d;
 memset(lx,0,sizeof(lx));
 memset(ly,0,sizeof(ly));
 memset(link,-1,sizeof(link));
 for(i=0;i<n;i++)
  for(j=0;j<n;j++)
   if(lx[i]<map[i][j])
    lx[i]=map[i][j];
   for(i=0;i<n;i++)
   {
    while(1)
    {
     memset(sx,0,sizeof(sx));
     memset(sy,0,sizeof(sy));
     d=inf;
     if(find(i))
      break;
     for(j=0;j<n;j++)
     {
      if(sx[j])
       for(k=0;k<n;k++)
        if(!sy[k])
        {
         if(d>lx[j]+ly[k]-map[j][k])
          d=lx[j]+ly[k]-map[j][k];
        }
     }
     for(j=0;j<n;j++)
     {
      if(sx[j])
       lx[j]-=d;
      if(sy[j])
       ly[j]+=d;
     }
    }
   }
   int sum=0;
   for(i=0;i<n;i++)
   {
    sum+=map[link[i]][i];
   }
   return sum;
}
int main()
{
 int i,j,k,h,t,t1,t2,p;
 char str[1000][100];
 while(scanf("%d%d",&k,&h),k||h)
 {
  n=0;
  memset(map,0,sizeof(map));
  for(i=0;i<k;i++)
  {
   scanf("%s",str[i]);
  for(j=0;j<h;j++)
   if(str[i][j]=='m')
    n++;
  }
  t1=0;t2=0;
  for(i=0;i<k;i++)
  {
   for(j=0;j<h;j++)
   {
    if(str[i][j]=='m')
    {
     for(p=0;p<k;p++)
      for(t=0;t<h;t++)
       if(str[p][t]=='H')
       {
        map[t1][t2]=-1*(abs(p-i)+abs(t-j));
        t2++;
       }
       t1++;
       t2=0;
    }
   }
  }
  for(i=0;i<k;i++)
   for(j=0;j<h;j++)
    if(map[i][j]==0)
     map[i][j]=-inf;
    printf("%d\n",-KM());
 }
 return 0;
}

 

 

原创粉丝点击