ZJU2013 Labyrinth - 树的最长路

题目描述:

一个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.

*/

你可能感兴趣的:(ZJU2013 Labyrinth - 树的最长路)