POJ-2195-Going Home
http://poj.org/problem?id=2195
最小费用最大流,假想一个源点,一个汇点
代码模仿网上的写的,还要再好好研究哇
#include<stdio.h>
#include<string.h>
#include<math.h>
#define maxn 300
#define INF 0x7fffffff
int min(int x,int y)
{
return x<y?x:y;
}
struct node
{
int x;
int y;
}h[maxn],man[maxn];
int map[maxn][maxn],vis[maxn],cap[maxn][maxn],dis[maxn];
int que[maxn],pre[maxn];
int num,ans;
int SPFA()
{
int i,k;
int head,tail;
memset(vis,0,sizeof(vis));
for(i=0;i<=num;i++)
dis[i]=INF;
dis[0]=0;
vis[0]=1;
head=tail=0;
que[0]=0;
tail++;
while(head<tail)
{
k=que[head];
vis[k]=0;
for(i=0;i<=num;i++)
{
if(cap[k][i]&&dis[i]>dis[k]+map[k][i])
{
dis[i]=dis[k]+map[k][i];
pre[i]=k;
if(!vis[i])
{
vis[i]=1;
que[tail++]=i;
}
}
}
head++;
}
if(dis[num]<INF)
return 1;
return 0;
}
void end()
{
int i,sum=INF;
for(i=num;i!=0;i=pre[i])
sum=min(sum,cap[pre[i]][i]);
for(i=num;i!=0;i=pre[i])
{
cap[pre[i]][i]-=sum;
cap[i][pre[i]]+=sum;
ans+=map[pre[i]][i]*sum;
}
}
int main()
{
int hnum,mnum,n,m,i,j;
char c;
while(scanf("%d%d",&n,&m)!=EOF,n||m)
{
hnum=0;
mnum=0;
getchar();
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%c",&c);
if(c=='H')
{
h[++hnum].x=i;
h[hnum].y=j;
}
else if(c=='m')
{
man[++mnum].x=i;
man[mnum].y=j;
}
}
getchar();
}
memset(cap,0,sizeof(cap));
memset(map,0,sizeof(map));
for(i=1;i<=mnum;i++)
{
for(j=1;j<=hnum;j++)
{
cap[i][j+mnum]=1;
map[i][j+mnum]=abs(man[i].x-h[j].x)+abs(man[i].y-h[j].y);
map[j+mnum][i]=-(map[i][j+mnum]);
}
}
num=mnum+hnum+1;
for(i=1;i<=mnum;i++)
{
map[0][i]=map[i][0]=0;
cap[0][i]=1;
}
for(i=mnum+1;i<num;i++)
{
map[i][num]=map[num][i]=0;
cap[i][num]=1;
}
ans=0;
while(SPFA())
end();
printf("%d\n",ans);
}
return 0;
}