POJ 2195 Going Home
又是一个二分最佳匹配!做过BFS搜索看这题就觉得思路比较清楚了,唯一的就是这次要最小代价!输入的图是一个字符型的!先BFS算距离!然后要处理的就是将距离值取负。这样可以直接用KM!
N次BFS,一次KM,效率还好,可能代码写的略长了!自己的风格,没去简化!
#include <iostream>
#include <stdio.h>
#include <string>
#include <queue>
usingnamespace std;
struct node
{
int x;
int y;
int dist;
};
#define N 501
char map[N][N];// 输入的图
int map1[N][N];// 得出的距离图
bool vis[N][N];//BFS 判断点是否走过
int vis2[N][N];//判断该点是下标 为map1做准备
int link[N]; //以后是KM准备
int visx[N];
int visy[N];
int dx[N],dy[N];
int r;
int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};//四方向
int n,m,lack;
queue <node > que;
void BFS(int k)
{
node p,q;
int i;
while(!que.empty())
{
p=que.front();
que.pop();
for(i=0;i<4;i++)
{
int dx=p.x+dir[i][0];
int dy=p.y+dir[i][1];
if(!vis[dx][dy]&&dx>0&&dy>0&&dy<=m&&dx<=n)
{
vis[dx][dy]=true;
q.dist=p.dist+1;
q.x=dx;
q.y=dy;
if(map[dx][dy]=='H')
map1[k][vis2[dx][dy]]=-q.dist; //距离取负 转换最大为最小
que.push(q);
}
}
}
}
int DFS(int v)
{
int i;
visx[v]=1;
for(i=1;i<=r;i++)
{
if(visy[i])
continue;
int t=dx[v]+dy[i]-map1[v][i];
if(!t)
{
visy[i]=true;
if(link[i]==-1||DFS(link[i]))
{
link[i]=v;
return1;
}
}
else
if(lack>t)
lack=t;
}
return0;
}
int KM()
{
int i,j;
memset(dx,0,sizeof(dx));
memset(dy,0,sizeof(dy));
memset(link,-1,sizeof(link));
for(i=1;i<=r;i++)
{
while(true)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
lack=0xffffff;
if(DFS(i))
break;
for(j=1;j<=r;j++)
{
if(visx[j])
dx[j]-=lack;
if(visy[j])
dy[j]+=lack;
}
}
}
int ans=0;
for(i=1;i<=r;i++)
ans+=dx[i]+dy[i];
return ans;
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
{
memset(map,'#',sizeof(map));
memset(vis2,0,sizeof(vis2));
int k=1; //用来算多少个点
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]=='H')
vis2[i][j]=k++;
}
k=1;
memset(map1,0,sizeof(map1));
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(map[i][j]=='m')
{
memset(vis,0,sizeof(vis));
node p;
while(!que.empty())
que.pop();
p.x=i;
p.y=j;
p.dist=0;
que.push(p);
BFS(k); //BFS扫图
k++;
}
r=k-1;
printf("%d\n",-KM()); //答案取负
}
return0;
}
#include <iostream>
#include <stdio.h>
#include <string>
#include <queue>
usingnamespace std;
struct node
{
int x;
int y;
int dist;
};
#define N 501
char map[N][N];// 输入的图
int map1[N][N];// 得出的距离图
bool vis[N][N];//BFS 判断点是否走过
int vis2[N][N];//判断该点是下标 为map1做准备
int link[N]; //以后是KM准备
int visx[N];
int visy[N];
int dx[N],dy[N];
int r;
int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};//四方向
int n,m,lack;
queue <node > que;
void BFS(int k)
{
node p,q;
int i;
while(!que.empty())
{
p=que.front();
que.pop();
for(i=0;i<4;i++)
{
int dx=p.x+dir[i][0];
int dy=p.y+dir[i][1];
if(!vis[dx][dy]&&dx>0&&dy>0&&dy<=m&&dx<=n)
{
vis[dx][dy]=true;
q.dist=p.dist+1;
q.x=dx;
q.y=dy;
if(map[dx][dy]=='H')
map1[k][vis2[dx][dy]]=-q.dist; //距离取负 转换最大为最小
que.push(q);
}
}
}
}
int DFS(int v)
{
int i;
visx[v]=1;
for(i=1;i<=r;i++)
{
if(visy[i])
continue;
int t=dx[v]+dy[i]-map1[v][i];
if(!t)
{
visy[i]=true;
if(link[i]==-1||DFS(link[i]))
{
link[i]=v;
return1;
}
}
else
if(lack>t)
lack=t;
}
return0;
}
int KM()
{
int i,j;
memset(dx,0,sizeof(dx));
memset(dy,0,sizeof(dy));
memset(link,-1,sizeof(link));
for(i=1;i<=r;i++)
{
while(true)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
lack=0xffffff;
if(DFS(i))
break;
for(j=1;j<=r;j++)
{
if(visx[j])
dx[j]-=lack;
if(visy[j])
dy[j]+=lack;
}
}
}
int ans=0;
for(i=1;i<=r;i++)
ans+=dx[i]+dy[i];
return ans;
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
{
memset(map,'#',sizeof(map));
memset(vis2,0,sizeof(vis2));
int k=1; //用来算多少个点
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]=='H')
vis2[i][j]=k++;
}
k=1;
memset(map1,0,sizeof(map1));
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(map[i][j]=='m')
{
memset(vis,0,sizeof(vis));
node p;
while(!que.empty())
que.pop();
p.x=i;
p.y=j;
p.dist=0;
que.push(p);
BFS(k); //BFS扫图
k++;
}
r=k-1;
printf("%d\n",-KM()); //答案取负
}
return0;
}