04:城市距离
总时间限制: 1000ms 内存限制: 65535kB
描述
某个国家的地图可以看做是一个n*m的表格,单元格为’#’表示城市区域,单元格为’.’表示耕地区域。连通的’#’表示的区域是同一个城市。从一个单元格走到上下左右相邻的另一个单元格为一步。现在,你可以选择在任何一个城市的任何一个单元格中,请问你要走到其他的城市中去,最少要走多少步?
输入
第一行两个整数n和m。(1<=n,m<=500)
接下来有n行,每行一个字符串,有m个字符,每个字符要么是’#’,要么是’.’。
保证地图中至少有两个城市。
输出
最近两个城市的距离。
样例输入
4 4
##..
...#
#...
....
样例输出
2
思路点拔:由于可以有不止一个’#’,所以首先需要一个搜索,搜索每
个城市,接着,用第二个搜索去遍历每个城市之间的距离,找到最小的距
离即可
法1:
#include<cstdio>
#include<queue>
#include<climits>
#include<cstring>
#include<iostream>
using namespace std;
struct node
{
int x,y;
};
struct dis
{
int x,y,time;
};
queue<node> q1;
queue<dis> q2;
int n,m;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}},ans=INT_MAX,tot=0,map[505][505];
bool flag1[505][505],flag2[505][505],maze[505][505];
void bfs2(int k);
void bfs1(int xx,int yy,int k)
{
int dx,dy;
map[xx][yy]=k;
node t;
t.x=xx;t.y=yy;
dis tt;
tt.x=xx;tt.y=yy;tt.time=0;
q1.push(t);
q2.push(tt);
while(!q1.empty()) //判断队列是否为空
{
node t1=q1.front();
q1.pop();
for(int i=0;i<4;i++) //枚举四个方向
{
dx=t1.x+dir[i][0];
dy=t1.y+dir[i][1];
if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!flag1[dx][dy]&&maze[dx][dy])
//判断有没有越界
{
flag1[dx][dy]=true;
map[dx][dy]=k;
node t3;
t3.x=dx;
t3.y=dy;
tt.x=dx;tt.y=dy;tt.time=0;
q2.push(tt);
q1.push(t3);
}
}
}
bfs2(k); //计算城市间的最短距离
}
void bfs2(int k)
{
memset(flag2,false,sizeof(flag2));
int dx,dy;
while(!q2.empty()) //判断队列是否为空
{
dis t1=q2.front();
q2.pop();
for(int i=0;i<4;i++) //枚举四个方向
{
dx=t1.x+dir[i][0];
dy=t1.y+dir[i][1];
if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!flag2[dx][dy]&&map[dx][dy]!=k)
{
dis t3;
t3.x=dx;
t3.y=dy;
t3.time=t1.time+1;
if(map[t3.x][t3.y]!=0) //计算最短距离
{
ans=min(ans,t3.time);
}
else
{
flag2[dx][dy]=true;
q2.push(t3);
}
}
}
}
}
int main()
{
char c;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%*c");
for(int j=1;j<=m;j++)
{
scanf("%c",&c);
if(c=='#')
{
map[i][j]=-1;
maze[i][j]=1;
}
else
{
map[i][j]=0;
maze[i][j]=0;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(maze[i][j]&&!flag1[i][j])
{
flag1[i][j]=true;
tot++;
bfs1(i,j,tot);
}
}
}
printf("%d\n",ans);
return 0;
}
法2(就是写一个判断越界的函数而已):
#include<cstdio>
#include<queue>
#include<climits>
#include<cstring>
#include<iostream>
using namespace std;
struct node
{
int x,y;
};
struct dis
{
int x,y,time;
};
queue<node> q1;
queue<dis> q2;
int n,m;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}},ans=INT_MAX,tot=0,map[505][505];
bool flag1[505][505],flag2[505][505],maze[505][505];
bool inside(int xa,int ya) //判断是否越界
{
if(xa<1||xa>n||ya<1||ya>m)
return false;
return true;
}
void bfs2(int k) //算出最短距离
{
memset(flag2,false,sizeof(flag2)); //清空数组
int dx,dy;
while(!q2.empty())
{
dis t1=q2.front();
q2.pop();
for(int i=0;i<4;i++)
{
dx=t1.x+dir[i][0]; //四个方向
dy=t1.y+dir[i][1];
if(inside(dx,dy)==true&&!flag2[dx][dy]&&map[dx][dy]!=k)
{
dis t3;
t3.x=dx;
t3.y=dy;
t3.time=t1.time+1;
if(map[t3.x][t3.y]!=0) //算出最短距离
{
ans=min(ans,t3.time);
}
else
{
flag2[dx][dy]=true;
q2.push(t3);
}
}
}
}
}
void bfs1(int xx,int yy,int k) //搜索城市,并将在、城市赋为'1'(标准广搜)
{
int dx,dy;
map[xx][yy]=k;
node t;
t.x=xx;
t.y=yy;
dis tt;
tt.x=xx;
tt.y=yy;
tt.time=0;
q1.push(t);
q2.push(tt);
while(!q1.empty()) //判断队列是否为空
{
node t1=q1.front();
q1.pop();
for(int i=0;i<4;i++)
{
dx=t1.x+dir[i][0];
dy=t1.y+dir[i][1];
if(inside(dx,dy)&&!flag1[dx][dy]&&maze[dx][dy])
{
flag1[dx][dy]=true;
map[dx][dy]=k;
node t3;
t3.x=dx;
t3.y=dy;
tt.x=dx;
tt.y=dy;
tt.time=0;
q2.push(tt);
q1.push(t3);
}
}
}
bfs2(k); //计算出城市间的最短距离
}
int main()
{
char c;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%*c");
for(int j=1;j<=m;j++)
{
scanf("%c",&c);
if(c=='#')
{
map[i][j]=-1;
maze[i][j]=1;
}
else
{
map[i][j]=0;
maze[i][j]=0;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(maze[i][j]&&!flag1[i][j])
{
flag1[i][j]=true;
tot++;
bfs1(i,j,tot);
}
}
}
printf("%d\n",ans);
return 0;
}
//本题是双结构体,双队列,双向搜索,代码量较大,再多梳理梳理