hznu 1852-走迷宫(dfs)

2024-01-31 01:58
文章标签 dfs 迷宫 1852 hznu

本文主要是介绍hznu 1852-走迷宫(dfs),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

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

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

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

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

Input
第一行: N 表示迷宫是 N*N 方阵 (2 ≤ N ≤ 100)

接下来有 N 行, 每一行包含 N 个整数,用来表示每个单元格中难度 (0 ≤ 任意难度 ≤ 120)。

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

Samples

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
output
2

我们可以知道答案的最小值为abs(左上角与右小角的差),最大值为方阵中的最大值和最小值的差。题目给的数据也不大(暴露了自己不会算dfs的时间复杂度),所以就开始暴力枚举。一开始写的时候,想的是每次去找已dfs的方格中的最大值和最小值,写出来是这样的。

bool check(int x, int y){if(x < 1 || y < 1|| x > n|| y > n || vis[x][y]) return false;maxx = max(maxx,mp[x][y]);minn = min(minn,mp[x][y]);if(maxx - minn > q) return false;return true;
}
bool dfs(int x, int y){for(int i=0;i<4;++i){int fx = x + Move[i][0];int fy = y + Move[i][1];int tmpn = minn;int tmpx = maxx;if(check(fx, fy)){
//			printf("%d %d\n",fx,fy);
//			printf("minn:%d maxx:%d\n",minn,maxx);if(fx == n && fy == n) return true;vis[fx][fy] = 1;if(dfs(fx, fy)) return true;vis[fx][fy] = 0;}minn = tmpn;maxx = tmpx;}return false;
}

此时我并没有发现走不通的路下一次就不用走了,造成了很大的时间浪费(我是真的不会算这个时间复杂度,悲)。
后来就上了二分,T了一会儿之后想到会不会限制的条件太少了,于是将差值用这条路径上的最大值和最小值来表示,并且改写了dfs,于是它就开始wa了

bool check(int x, int y){if(x < 1 || y < 1|| x > n|| y > n || vis[x][y]) return false;if(mp[x][y] > tail || mp[x][y] < head) return false;return true;
}
bool dfs(int x, int y){for(int i=0;i<4;++i){int fx = x + Move[i][0];int fy = y + Move[i][1];if(check(fx, fy)){
//			printf("%d %d\n",fx,fy);
//			printf("minn:%d maxx:%d\n",minn,maxx);if(fx == n && fy == n) return true;vis[fx][fy] = 1;if(dfs(fx, fy)){return true;}}}return false;
}
bool work(){memset(vis,0,sizeof(vis));for(int i=minn;i<=maxx - mid;++i){head = i;tail = i + mid;if(dfs(1,1)) return true;}return false;
}
int main(void){maxx = -1;minn = 121;scanf("%d",&n);for(int i =1;i<=n;++i){for(int j=1;j<=n;++j){scanf("%d",&mp[i][j]);maxx = max(maxx,mp[i][j]);minn = min(minn,mp[i][j]);}}int r = maxx - minn;
//	printf("%d\n",k);int l = abs(mp[n][n]-mp[1][1]);int ans=r;while(l <= r){mid = (l+r)>>1;
//		printf("mid:%d\n",mid);
//		maxx = mp[1][1];
//		minn = mp[1][1];vis[1][1]=1;if(work()){r = mid-1;ans = mid;}else l = mid+1;vis[1][1]=0;}printf("%d\n",ans);return 0;
}

然后就开始怀疑人生了。去超市买了桶面回来,又开始debug。突然想到是从(1,1)点开始的,所以最小值最大只能取到(1,1)点的值。终于ac了之后,又把二分改成了枚举,也能轻松ac。但是看到网上大部分题解都加了二分,可能hznuoj拉进来的时候弱化了数据?

#include<bits/stdc++.h>
using namespace std;
int mp[110][110],vis[110][110],Move[][2]={1,0,-1,0,0,1,0,-1};
int maxx,minn;
int n,mid;
int head,tail;
bool check(int x, int y){if(x < 1 || y < 1|| x > n|| y > n || vis[x][y]) return false;if(mp[x][y] > tail || mp[x][y] < head) return false;return true;
}
bool dfs(int x, int y){for(int i=0;i<4;++i){int fx = x + Move[i][0];int fy = y + Move[i][1];if(check(fx, fy)){if(fx == n && fy == n) return true;vis[fx][fy] = 1;if(dfs(fx, fy)){return true;}}}return false;
}
bool work(){for(int i=minn;i<=min(maxx - mid,mp[1][1]);++i){head = i;tail = i + mid;memset(vis,0,sizeof(vis));vis[1][1] = 1;if(dfs(1,1)) return true;}return false;
}
int main(void){maxx = -1;minn = 121;scanf("%d",&n);for(int i =1;i<=n;++i){for(int j=1;j<=n;++j){scanf("%d",&mp[i][j]);maxx = max(maxx,mp[i][j]);minn = min(minn,mp[i][j]);}}int r = maxx - minn;int l = abs(mp[n][n]-mp[1][1]);int ans=r;for(mid=l;mid<=r;++mid){if(work()){printf("%d\n",mid);return 0;}}return 0;
}

这篇关于hznu 1852-走迷宫(dfs)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/662234

相关文章

poj 1564 Sum It Up -- DFS 递归

题意:给一个数 t ,以及 n 个数,求 n 个数中的几个数加起来的和为 t 的情况有多少种。 注意:题目要求相同的组合方式不能出现2次,即 “3 4 1 1 1 1 ” 的结果为:“1+1+1”。 思路:一个  for  循环遍历一遍,每个 i 表示以当前数为起点开始一次DFS递归,当所遍历的和为 t 时,输出该组合方式,如果大于 t 则返回,小于则往下递归。以二维数组保存已经输出过的数据,

BFS【2】迷宫

目录 迷宫 走到右下角最短路径长度 走到右下角最短路径 跨步迷宫   迷宫 走到右下角最短路径长度 我是和上一篇一样,创建一个队列,不过while 里面判责是queue非空,否则会死循环万一是死路的话。 也是要判断不要重复入队。 #include <iostream>#include <vector>#include <cmath>#include <string>

洛谷 P1141 01迷宫 (dfs解决)

题目描述 有一个仅由数字 0 与 1 组成的 n×n 格迷宫。若你位于一格 0 上,那么你可以移动到相邻 4 格中的某一格 1 上,同样若你位于一格 1 上,那么你可以移动到相邻 4 格中的某一格 0 上。 你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。 输入格式 第一行为两个正整数 𝑛,𝑚。 下面 𝑛 行,每行 𝑛 个字符,字符只可能是 0 或者

[HDU 4324] Triangle LOVE (拓扑排序,DFS)

HDU - 4324 题意是,一张有 N个点的图,保证每两个点之间有且只有一条有向边连接 求是否存在三元环 用拓扑排序判环,如果存在环,则一定存在三元环 证明如下: 不存在二元环 设存在 n(n>=3)元环 p1->p2->p3->…->pn->p1 1) 若存在边 p3->p1,则存在三元环 (p1->p2->p3->p1) 2) 若不存在 p3->p1,则必然存在 p1->p3

[CSU - 1811 (湖南省赛16)] Tree Intersection (dfs序维护子树+离线询问+树状数组)

CSU - 1811 (湖南省赛16) 给定一棵树,每个节点都有一个颜色 问割掉任意一条边,生成的两个子树中颜色集合的交集大小 这个是 dfs序处理子树 + 离线询问 + bit维护 的解法 首先问题转化为求解一个子树中有多少种颜色以及独有颜色的数量 用总的颜色数量减去独有颜色数量即为这棵子树的答案 先做一遍 dfs,再按 dfs序重新组建颜色序列 这样对子树的询问,就变成

DFS走迷宫(懒猫老师C++完整版)

DFS走迷宫的C++完整版 知识储备一:普通动态二维数组的构造二:栈的构造三:栈的逆序遍历 Main文件代码 该版本代码是配合 懒猫老师用DFS走迷宫视频 基于C++基础所写的完整版(实现了栈逆序遍历),适合小白系统性的学习和复习知识点,只要将下文.h和.cpp和main文件所展示的代码结合起来就是个完整的代码。 知识储备 一:普通动态二维数组的构造 二维数组中不同行的内

fast DFS 单机使用实例

fast DFS 单机使用实例 我在一台服务器上简单测试了fastdfs。client, tracker, storage server都是同一个物理服务器。   1. 编译fastdfs:   sles207:/opt/mars/FastDFS # ./make.sh   storage_service.o: In function `storage_service_init':/opt/ma

[深度优先搜索DFS]迷宫问题

描述 定义一个二维数组: int maze[5][5] = {0, 1, 0, 0, 0,0, 1, 0, 1, 0,0, 0, 0, 0, 0,0, 1, 1, 1, 0,0, 0, 0, 1, 0,}; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。 输入 一个5 × 5的二维数组,表示一个迷宫。数

【LeetCode】 Surrounded Regions (BFS DFS)

题目:Surrounded Regions 广搜和深搜都能解决,但是LeetCode上使用深搜时会栈溢出 DFS: <span style="font-size:18px;">/*LeetCode Surrounded Regions* 题目:给定一个字符数组,由'X'和'O'组成,找到所有被x包围的o并将其替换为x* 思路:只要替换被包围的o就行,如果有一个o是边界或者上下左右中有一个

HDU 1044 BFS+DFS

先BFS出每个点之间的最小距离 然后DFS最优值 #include "queue"#include "iostream"#include "algorithm"using namespace std;int dir[4][2]={1,0,-1,0,0,1,0,-1};struct node{int x,y,step;};struct comp{int x,y;} mar