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;
}
posted @ 2011-08-05 17:09  Lxsec  阅读(188)  评论(0编辑  收藏  举报