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; }