题目描述:
一个n*m的地图, 求出相距最远的两个空地间之间的距离。保证地图中任意两个空地之间有且仅有一条路径。n,m<1000
分析:
可以看出,整个地图的路径可以构成一棵树。题目就是要求这棵树中距离最远的两个点。
假设我们已经把这棵树建好了,我用了一个很短的递归函数maxlen求出了这个树的最长路,这个递归函数返回以顶点p为根的树的深度:
1.若p是叶子,则返回0。
2.若p不是叶子,则计算它的每个子树的深度m=maxlen(son[i])+len[p,son[i]](注意,子树的个数不会超过3)
3.若子树的深度最大和次大之和大于ans,则更新ans的值。ans是外部变量记录当前的最长路。
4.返回最大的子树深度。
这个函数不到20行。要注意的是由于是矩阵地图,所以任意一个点相邻的空地最多4个,看作有向树的话,子树最多3个。在储存的时候可以节省一些空间和时间。
现在要做的就是把地图转换为树。
转换的时候使用广度优先搜索,也没太多技巧。只有遇到死胡同和岔路的点,才把它加入到树的节点中。
贴一下代码,2秒多AC的:
/*
ZJU2013 Labyrinth
*/
#include <stdio.h>
#include <string.h>
#define N 1002
#define clr(a) memset(a,0,sizeof(a))
struct nodepoint{
int x,len;
};
typedef struct nodepoint node;
struct nodesearch{
int x,y;
int f,len;
};
typedef struct nodesearch point;
int dir[][2]={{0,1},{0,-1},{1,0},{-1,0}};
int c,r;
int ans;
char a[N][N];
char e[N][N];
node b[N*N/2][4];
point d[N*N/2];
int out(int x,int y){
if(x<0||y<0||x>=r||y>=c) return 1;
else return 0;
}
int neighbour(int x0,int y0,char ch)
{
int i,c=0,x,y;
for(i=0;i<4;i++){
x=x0+dir[i][0];
y=y0+dir[i][1];
if(!out(x,y)&&a[x][y]==ch&&!e[x][y])
c++;
}
return c;
}
//creat a tree
int creattree(char a[][N],node b[][4])
{
int i,j,k,p,q,m,n;
int x,y,x0,y0;
int f,len,flag;
//get first point
flag=1;
for(x=0;x<r&&flag;x++)
for(y=0;y<c&&flag;y++)
if(a[x][y]=='.') flag=0;
if(a[--x][--y]!='.') return 0;
m=0;
p=0;q=1;
d[0].x=x;
d[0].y=y;
d[0].f=0;
d[0].len=0;
e[x][y]=1;
//BFS
while(p<q)
{
f=d[p].f;
len=d[p].len;
x0=d[p].x;
y0=d[p].y;
//new node
if(neighbour(x0,y0,'#')==3||neighbour(x0,y0,'.')>1){
m++;
n=++b[f][0].x;
b[f][n].x=m;
b[f][n].len=len;
f=m;
len=0;
}
//each dir
for(k=0;k<4;k++){
x=x0+dir[k][0];
y=y0+dir[k][1];
if(out(x,y)) continue;
//add point
if(a[x][y]=='.'&&!e[x][y]){
d[q].x=x;
d[q].y=y;
d[q].f=f;
d[q].len=len+1;
e[x][y]=1;
q++;
}
}
p++;
}//end BFS
return m;
}
//return the max depth under node p
int maxlen(int p)
{
int i,j,n;
int len,m,m1,m2;
n=b[p][0].x;
len=m1=m2=0;
for(i=1;i<=n;i++){
m=maxlen(b[p][i].x)+b[p][i].len;
if(m>=m1){
m2=m1;
m1=m;
}else if(m>=m2){
m2=m;
}
}
len=m1+m2;
if(len>ans) ans=len;
return m1;
}
int main()
{
int i,j,k,m,n,T;
scanf("%d",&T);
while(T--)
{
//init
clr(a); clr(b);
clr(d); clr(e);
//input
scanf("%d%d",&c,&r);
getchar();
for(i=0;i<r;i++)
gets(a[i]);
//creat tree
n=creattree(a,b);
ans=0;
if(n>1) maxlen(1);
//output
printf("Maximum rope length is %d./n",ans);
}
//system("pause");
return 0;
}
/*
Sample Input
3
3 3
###
#.#
###
7 6
#######
#.#.###
#.#.###
#.#.#.#
#.....#
#######
7 6
#######
#.....#
#.#.###
#.#.#.#
#.#...#
#######
Sample Output
Maximum rope length is 0.
Maximum rope length is 8.
Maximum rope length is 11.
*/