可以KM,也可以費用流,最近學費用流,所以用一下,debug真浪費時間,以為spfa有問題,原來是計數時出錯。。。囧啊,菜啊,話說poj 2516到現在還不知道wa哪裡,抓狂啊!!!
#define inf 1<<30#define N 222int cap[N][N];int cost[N][N];int pre[N];int dis[N];bool vis[N];int minc;char str[110][110];int min(int a,int b){return a>b?b:a;}void spfa(int s,int t){ queue<int> qq; int i,j; while(1){ for(i=s;i<=t;i++){ vis[i] = 0; dis[i] = inf; } dis[s] = 0; qq.push(s); vis[s] = 1; while(!qq.empty()){ int u = qq.front(); qq.pop(); vis[u] = 0; for(int v=s;v<=t;v++){ if(cap[u][v] && dis[u] + cost[u][v] < dis[v]){ dis[v] = dis[u] + cost[u][v]; pre[v] = u; if(!vis[v]){ vis[v] = 1; qq.push(v); } } } } if(dis[t] == inf){ return ; } int a = inf; for(int u=t;u!=s;u=pre[u]){ a = min(a,cap[pre[u]][u]); } for(int u=t;u!=s;u=pre[u]){ cap[pre[u]][u] -= a; cap[u][pre[u]] += a; } minc += dis[t]*a; } return ;}struct node{ int r,c;}mm[N/2],hh[N/2];int cntm ;int cnth ;void work(){ int i,j; int s = 0,t = cntm + cnth + 1; minc =0; memset(cap,0,sizeof(cap)); memset(cost,0,sizeof(cost)); for(i=1;i<=cntm;i++){ cap[s][i] = 1;//每條邊容量為1,最後肯定是滿流的 cost[s][i] = 0; } for(i=1;i<=cnth;i++){ cap[i+cntm][t] = 1; cost[i+cntm][t] = 0; } for(i=1;i<=cntm;i++){ for(j=1;j<=cnth;j++){ cap[i][j+cntm] = 1; cost[i][j+cntm] = abs(mm[i].r - hh[j].r) + abs(mm[i].c - hh[j].c); cost[j+cntm][i] = -cost[i][j+cntm];//注意要取反 } } spfa(s,t); printf("%d\n",minc);}int main(){ int n,m; while(scanf("%d%d",&n,&m) && (n+m)){ int i,j; for(i=1;i<=n;i++){ scanf("%s",str[i]+1); } cntm = 0; cnth = 0; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ if(str[i][j] == 'm'){ mm[++cntm].r = i; mm[cntm].c = j; } else if(str[i][j] == 'H'){ hh[++cnth].r = i; hh[cnth].c = j; } } }cout<<cntm<<endl; work(); } return 0;}