计算房间和人的距离的时候,我一开始竟然想到用巨烦无比的 BFS !!!
这不就是曼哈顿距离嘛!!
然后改成这个简单的距离函数,就OK 啦。
默默的把源点和人连起来,把人和所有房子连起来,房子和汇点连起来,默默的来一发费用流。。。
宏是个好东西 不能不用 啊 ZWJ !
#include <stdio.h>
#include <queue>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <string.h>
#include <vector>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define MAX 2222
#define P pair<int,int>
#define fst first
#define sec second
#define ll long long
#define MI map< P, int> :: iterator
char b[200][200];
int n,m;
int nh,nm;
map< P, int> mph;
map< P, int> mpm;
struct edge
{
int to,cap,cost,rev;
};
vector<edge> G[MAX];
void addEdge(int f,int t,int cap,int cost)
{
G[f].push_back((edge){t,cap,cost,G[t].size()});
G[t].push_back((edge){f,0,-cost,G[f].size()-1});
}
int V;
int dista[200][200];
int prevv[MAX];
int preve[MAX];
int min_cost_flow(int s,int t,int f)
{
int dist[MAX];
int ans=0;
while(f>0)
{
for(int i=0;i<MAX;i++)
dist[i]=INF;
dist[s]=0;
bool update=true;
while(update)
{
update=false;
for(int i=0;i<V;i++)
{
if(dist[i]==INF) continue;
for(int j=0;j<G[i].size();j++)
{
edge te=G[i][j];
if(te.cap>0&&dist[te.to]>dist[i]+te.cost)
{
update=true;
dist[te.to]=dist[i]+te.cost;
prevv[te.to]=i;
preve[te.to]=j;
}
}
}
}
if(dist[t]==INF)
return -1;
int p=f;
for(int v=t;v!=s;v=prevv[v])
p=min(p,G[prevv[v]][preve[v]].cap);
f-=p;
ans+=p*dist[t];
for(int v=t;v!=s;v=prevv[v])
{
edge &e=G[prevv[v]][preve[v]];
e.cap-=p;
G[v][e.rev].cap+=p; // 因为这个是倒着来的 所以 V 就是其反向边
}
}
return ans;
}
int abs(int a)
{
return a>0?a:-a;
}
int juli(P a, P b)
{
return abs(a.fst-b.fst)+abs(a.sec-b.sec);
}
void setDis()
{
for(MI itm=mpm.begin();itm!=mpm.end();itm++)
{
P f=itm->fst;
for(MI ith=mph.begin();ith!=mph.end();ith++)
{
P t=ith->fst;
dista[itm->sec][ith->sec]=juli(f,t);
}
}
}
int main()
{
freopen("acm.in","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF&&(n!=0||m!=0))
{
nh=nm=0;
for(int i=0;i<MAX;i++) G[i].clear();
mpm.clear(),mph.clear();
for(int i=0;i<n;i++)
{
scanf("%s",b[i]);
for(int j=0;j<m;j++)
{
if(b[i][j]=='H')
mph[P(i,j)]=nh++;
if(b[i][j]=='m')
mpm[P(i,j)]=nm++;
}
}
setDis();
V=2+nm+nh;
int S=0,T=V-1;
for(int i=0;i<nm;i++)
for(int j=0;j<nh;j++)
{
addEdge(i+1,j+nm+1,INF,dista[i][j]);
}
for(int i=0;i<nm;i++)
addEdge(0,i+1,1,0);
for(int j=0;j<nh;j++)
addEdge(j+nm+1,T,1,0);
int ans=min_cost_flow(S,T,nm);
cout<<ans<<endl;
}
return 0;
}