poj 2195 Going Home (最小费用 最大流)

  1 /*

  2 将 maxn 定位 200  不是超时 就是wa 定位300 32ms 过  纠结。。。。。。。 

  3 

  4 题意:一个row*col的矩阵,m表示人,H表示房子,.表示空地,人数和房子数相等,如下图:

  5         5 5

  6         HH..m

  7         .....

  8         .....

  9         .....

 10         mm..H

 11 现在要让所有的人都进入不同的房子内,问总共最少走多少步?

 12 将 人看作是 源点 房子 看作是 汇点

 13  

 14 思路:最小费用最大流。

 15 

 16 */

 17 

 18 #include<stdio.h>

 19 #include<string.h>

 20 #define maxn 300

 21 #define inf 0x7fffffff

 22 #include<cmath>

 23 int min(int x,int y)

 24 {

 25     if(x<y)return x;

 26     else return y;

 27 }

 28 struct node

 29 {

 30     int x;

 31     int y;

 32 }h[maxn],man[maxn];

 33 int map[maxn][maxn],vis[maxn],cap[maxn][maxn],dis[maxn];

 34 int que[maxn],pre[maxn];

 35 int num,ans;

 36 int SPFA()

 37 {

 38 

 39     int i;

 40     memset(vis,0,sizeof(vis));

 41      for(i=0;i<=num;i++)dis[i]=inf;

 42      dis[0]=0;

 43      vis[0]=1;

 44 

 45      int head=0,tail=0;

 46      que[0]=0;

 47      tail++;

 48      while(head!=tail)

 49      {

 50          int k=que[head];

 51 

 52          vis[k]=0;

 53          for(i=0;i<=num;i++)

 54          {

 55              if(cap[k][i]&&dis[i]>dis[k]+map[k][i])

 56              {

 57                  dis[i]=dis[k]+map[k][i];

 58                  pre[i]=k;

 59 

 60                  if(!vis[i])

 61                  {

 62                      vis[i]=1;

 63                      que[tail++]=i;

 64                      if(tail==maxn)tail=0;

 65                  }

 66              }

 67          }

 68          head++;

 69          if(head==maxn)head=0;

 70 

 71      }

 72      if(dis[num]<inf)return 1;//这里要注意 和最大流的不同

 73      else

 74      return 0;

 75 }

 76 void end()

 77 {

 78     int i,sum=inf;

 79     for(i=num;i!=0;i=pre[i])

 80     {

 81         sum=min(sum,cap[pre[i]][i]);

 82     }

 83     for(i=num;i!=0;i=pre[i])

 84     {

 85         cap[pre[i]][i]-=sum;

 86         cap[i][pre[i]]+=sum;

 87         ans+=map[pre[i]][i]*sum;

 88     }

 89 

 90 }

 91 int main()

 92 {

 93     int hnum,mnum,n,m,i,j;

 94     char c;

 95     while(scanf("%d%d",&n,&m)!=EOF)

 96     {

 97         if(n==0&&m==0)break;

 98         hnum=0;

 99         mnum=0;

100         getchar();

101         for(i=0;i<n;i++)

102         {

103             for(j=0;j<m;j++)

104             {

105                 scanf("%c",&c);

106                 if(c=='H')

107                 {

108                     h[++hnum].x=i;

109                     h[hnum].y=j;

110                 }

111                 if(c=='m')

112                 {

113                     man[++mnum].x=i;

114                     man[mnum].y=j;

115                 }

116             }

117             getchar();

118         }

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

120         memset(map,0,sizeof(map));

121         for(i=1;i<=mnum;i++)

122         {

123 

124             for(j=1;j<=hnum;j++)

125             {

126 

127                 cap[i][j+mnum]=1;

128                 map[i][j+mnum]=fabs(man[i].x-h[j].x)+fabs(man[i].y-h[j].y);

129                 map[j+mnum][i]=-map[i][j+mnum];

130             }

131         }

132         num=mnum+hnum+1;

133         for(i=1;i<=mnum;i++)

134         {

135             map[0][i]=map[i][0]=0;

136             cap[0][i]=1;

137 

138         }

139         for(i=mnum+1;i<num;i++)

140         {

141             map[i][num]=map[num][i]=0;

142             cap[i][num]=1;

143         }

144         ans=0;

145         while(SPFA())end();

146         printf("%d\n",ans);

147 

148 

149     }

150 }

你可能感兴趣的:(home)