走迷宫

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

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

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

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

 
输入
有多组测试数据,以EOF为输入结束的标志
第一行: N 表示迷宫是N*N方阵 (2≤ N≤ 100)
接下来有N行, 每一行包含N个整数,用来表示每个单元格中难度 (0≤任意难度≤120)。
输出
输出为一个整数,表示路径上最高难度与和最低难度的差。
样例输入
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
样例输出
2
来源
第四届河南省程序设计大赛
上传者
张云聪
上下左右四个方向,走的方式太多了简直无法暴力搜索。难度差最大为120,考虑从这里下手,
找出迷宫中的最大值与最小值,这两个数的差值就是最大的难度差,最小的难度差为零,然后二分在这个区间里枚举难度差直到找到最优解。
切记不要多此一举的回溯,这样会导致TLE(并不是每个搜索都需要回溯)。
找到mid=(l+r)/2,然后把难度差控制在[l,mid]直接搜索,若有解则将r的值更新为mid,否则将l的值更新为mid+1,每次都会缩小一半的范围;
对于给定的一个mid,找到所有符合条件的区间逐个枚举,发现路径后及时退出。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,ok,e[105][105];
int minn=999999999,maxn=-1;
bool vis[105][105];
int fx[4][2]={-1,0,1,0,0,1,0,-1};
int read()
{
int s=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') {s=s*10+ch-'0';ch=getchar();}
return s;
}
void dfs(int x,int y,int l,int r)
{
if(ok) return;
if(x==n&&y==n) {ok=1;return;}
for(int i=0;i<4;++i){if(ok) return;
int dx=x+fx[i][0];
int dy=y+fx[i][1];
if(dx>=1&&dy>=1&&dx<=n&&dy<=n&&e[dx][dy]>=l&&e[dx][dy]<=r&&!vis[dx][dy]){
vis[dx][dy]=1;
dfs(dx,dy,l,r);
//vis[dx][dy]=0;
}
}
}
bool Find(int k)
{
for(int i=minn;i+k<=maxn;++i){

if(e[1][1]<i||e[1][1]>i+k) continue;//当前地图值不在查找范围内
if(e[n][n]<i||e[n][n]>i+k) continue;
ok=0;
memset(vis,0,sizeof(vis));
vis[1][1]=1;
dfs(1,1,i,i+k);
if(ok) return true;
}
return false;
}
int solve()
{
int l=0,r=maxn-minn,mid;
while(l<r){
mid=(l+r)/2; //cout<<mid<<endl;
if(Find(mid)) r=mid;
else l=mid+1;
}
return l;
}
int main()
{
int i,j;
while(cin>>n){minn=999999999;maxn=-1;
for(i=1;i<=n;++i)
for(j=1;j<=n;++j) {e[i][j]=read();
if(e[i][j]<minn) minn=e[i][j];
if(e[i][j]>maxn) maxn=e[i][j];
}//cout<<minn<<" "<<maxn<<endl;
printf("%d\n",solve());
}
return 0;
}

nyoj306 二分+DFS的更多相关文章

  1. Codeforces Round #381 (Div. 2)D. Alyona and a tree(树+二分+dfs)

    D. Alyona and a tree Problem Description: Alyona has a tree with n vertices. The root of the tree is ...

  2. [BZOJ 1082] [SCOI2005] 栅栏 【二分 + DFS验证(有效剪枝)】

    题目链接:BZOJ - 1082 题目分析 二分 + DFS验证. 二分到一个 mid ,验证能否选 mid 个根木棍,显然要选最小的 mid 根. 使用 DFS 验证,因为贪心地想一下,要尽量先用提 ...

  3. 51nod1307(暴力树剖/二分&dfs/并查集)

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307 题意: 中文题诶~ 思路: 解法1:暴力树剖 用一个数 ...

  4. 【BZOJ】1082: [SCOI2005]栅栏(二分+dfs)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1082 题意:n个给出木板,m个给出木板.可以将那m个木板锯成泥想要的长度.问最大能锯成多少个给出的n ...

  5. 【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...

  6. (hdu)5652 India and China Origins 二分+dfs

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5652 Problem Description A long time ago there ...

  7. 第四届河南省省赛 走迷宫 二分+DFS

    题目思路:使用二分查找路径中最大值和最小值之间的差值,从而确定出一组minn和maxn,对此组的minn和maxn经行DFS,如果可以找到一条路径,其中的最大值,最小值在minn~maxn的范围内,则 ...

  8. [SCOI2005]栅栏 二分+dfs

    这个题真的是太nb了,各种骚 二分答案,肯定要减最小的mid个,从大往小搜每一个木板,从大往小枚举所用的木材 当当前木材比最短的木板还短,就扔到垃圾堆里,并记录waste,当 waste+sum> ...

  9. BZOJ 1082 栅栏(二分+DFS剪枝)

    首先,长度短的木板一定比长度长的木板容易得到,因此若要得到最多的木板,它们必定是所有木板中最短的——可以对木板排序后二分答案(用k表示). 判断是否合法就用搜索,但数据有点大,要用到两个剪枝.一个是若 ...

随机推荐

  1. python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法

    python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法 同一台机器同时安装 python2.7 和 python3.4不会冲突.安装在不同目录,然 ...

  2. clock_gettime接口和linux时间系统

    RTC/OSCRTC,Real Time Clock,真实时钟,也叫做CMOS时钟,又叫walltimeOSC,Operation System Clock,系统时钟.在开机时操作系统取得RTC中的时 ...

  3. 关于hibernate中的session与数据库连接关系以及getCurrentSession 与 openSession() 的区别

    1.session与connection,是多对一关系,每个session都有一个与之对应的connection,一个connection不同时刻可以供多个session使用.   2.多个sessi ...

  4. SQL 报表 --简易进销系统

    模型图: -- ============================================ -- Author: lifu -- Create Date: 2017-06-18 -- D ...

  5. Java并发之FairSync和NonfairSync

    Java并发中的fairSync和NonfairSync主要区别为: 如果当前线程不是锁的占有者,则NonfairSync并不判断是否有等待队列,直接使用compareAndSwap去进行锁的占用; ...

  6. 从一道题看线程安全--牛客网Java基础题

    从一道题看线程安全 Java中的线程安全是什么: 就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的 ...

  7. C# 将 Stream 写入文件

    public void StreamToFile(Stream stream,string fileName) { // 把 Stream 转换成 byte[] byte[] bytes = new ...

  8. linux下kermit工具的使用

    1.环境: ubuntu16.04 2.背景: 想更换下位机内核 3.使用kermit进行串口传输 举例:传输文件到下位机 2.1首先进入下位机的uboot 2.2 使用uboot自带的命令从串口接收 ...

  9. xshell5 Linux 上传下载文件

    1,先登录身份验证和文件传输ZMODEM 选择自动激活. 2,rpm -qa | grep lrzsz 利用此命令查看是否安装了lrzsz . 如果没有任何反应则是没有安装 若没有安装 yum ins ...

  10. The way to Go(6): Go程序的基本结构和要素

    Reference: Github: Go Github: The way to Go Go程序的基本结构和要素 helloworld.go: package main import "fm ...