COJ1143(走迷宫)

Description

Dr.Kong设计的机器人卡多非常爱玩,它常常偷偷跑出实验室,在某个游乐场玩之不疲。这天卡多又跑出来了,在SJTL游乐场玩个不停,坐完碰碰车,又玩滑滑梯,这时卡多又走入一个迷宫。个迷宫是用一个N * N的方阵给出方阵中单元格中填充了一整数,表示走到这个位置的难度。

这个迷宫可以向上走,向下走,向右走,向左走,但是不能穿越对角线。迷宫的取胜规则很有意思,看谁能更快地找到一条路径,其路径上单元格最大难度值与最小难度值之差是最小的。当然了,或许这样的路径不是最短路径。

     机器人卡多现在在迷宫的左上角(第一行,第一列)而出口迷宫的右下角(第N行,第N列)。

卡多很聪明,很快就找到这样一条路径。你能找到吗?

Input

有多组测试数据,以EOF为输入结束的标志
第一行: N 表示迷宫是N*N方阵 (2≤ N≤ 100)
接下来有N行, 每一行包含N个整数,用来表示每个单元格中难度 (0≤任意难度≤120)。

Output

输出为一个整数,表示路径上最高难度与和最低难度的差。

Sample Input

5
1 1 3 6 8
1 2 2 5 5
4 4 0 3 3
8 0 2 3 4
4 3 0 2 1

Sample Output

2
 
这题放了很久了,以前用dfs暴搜总是超时,也想不到什么好的剪枝方法,所以一直没A,今天突然想到可以用二分来枚举难度差,用dfs来判断能否在给定的难度差下完成任务,这样处理后复杂度骤降,自然也就AC了。
View Code
#include <stdio.h>

#include <string.h>

#define MIN(a,b) ((a)<(b)?(a):(b))

#define MAX(a,b) ((a)>(b)?(a):(b))

#define N 100

int dx[4]={0,0,1,-1};

int dy[4]={1,-1,0,0};

int map[N][N],vis[N][N];

int n,L,H;

int small,big;

bool success;

void dfs(int x,int y)

{

    int i,nx,ny;

    if(map[x][y]<L || map[x][y]>H)  return;

    if(x==n-1 && y==n-1)

    {

        success=true;

        return;

    }

    for(i=0;i<4;i++)

    {

        nx=x+dx[i];

        ny=y+dy[i];

        if(nx<0 || nx>=n || ny<0 || ny>=n || vis[nx][ny])  continue;

        vis[nx][ny]=1;

        dfs(nx,ny);

    }

}

bool judge(int d)

{

    int i;

    for(i=small;i+d<=big;i++)

    {

        L=i;

        H=i+d;

        success=false;

        memset(vis,0,sizeof(vis));

        vis[0][0]=1;

        dfs(0,0);

        if(success) break;

    }

    if(i+d<=big)    return true;

    return false;

}

int main()

{

    int i,j;

    int min,max,mid;

    while(~scanf("%d",&n))

    {

        small=120;

        big=0;

        for(i=0;i<n;i++)

        {

            for(j=0;j<n;j++)

            {

                scanf("%d",&map[i][j]);

                small=MIN(small,map[i][j]);

                big=MAX(big,map[i][j]);

            }

        }

        min=-1;

        max=big-small;

        while(min+1!=max)

        {

            mid=(min+max)>>1;

            if(judge(mid))  max=mid;

            else    min=mid;

        }

        printf("%d\n",max);

    }

    return 0;

}

 

你可能感兴趣的:(OJ)