• 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;
    }
  • 相关阅读:
    第一次博客作业
    201771010110孔维滢《面向对象程序设计(java)》第二周学习总结
    孔维滢201771010110《面向对象程序设计(java)》第一周学习总结
    2018-2019-1 20165230《信息安全系统设计基础》第二周学习总结
    # 2018-2019-1 20165230 《信息安全系统设计基础》第三周学习总结
    20165230 获奖感想与学习心得
    20165230 2017-2018-2《Java程序设计》课程总结
    20165230 《Java程序设计》实验五《网络编程与安全》实验报告
    20165230 《Java程序设计》实验四 Android程序设计实验报告
    20165230 《Java程序设计》实验三 敏捷开发与XP实践 实验报告
  • 原文地址:https://www.cnblogs.com/algorithms/p/2584420.html
Copyright © 2020-2023  润新知