搜索专题:问题 E: 挑战ACM迷宫
这是往年校赛的一道题,最开始做这道题的时候还没有系统的学习过搜索,用了C语言学的回溯法尝试,毫无疑问的TLE;
学习了DFS之后,自己的剪枝功力不够,又是TLE,最后学了BFS之后,哇,终于做出来了,别提多开心了,然后意识到这道题其实很简单的,剋以用BFS标记法和更改步数法(更改最小消耗),后来发现这种题也可以建图跑迪杰斯特拉做;
BFS标记法:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int N = 100 + 5;
int mat[N][N];
bool visit[N][N];
typedef struct node{
int x,y,val;
bool operator < (const node x)const {
return val > x.val;
}
}Node;
const int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
int BFS(int n){
priority_queue<Node> Q;
Node t;
memset(visit,0,sizeof(visit));
int x=0,y=0,goalx=n-1,goaly=n-1,newx,newy;
t=(Node){x,y,mat[x][y]};
visit[x][y] = true;
Q.push(t);
while(!Q.empty()){
t = Q.top();Q.pop();
if(t.x == goalx && t.y == goaly) return t.val;
for(int d=0;d<4;d++){
newx = t.x + dir[d][0];
newy = t.y + dir[d][1];
if(newx>=0 && newx<n && newy>=0 && newy<n && mat[newx][newy] && !visit[newx][newy]){
visit[newx][newy] = true;
Q.push((Node){newx,newy,t.val+mat[newx][newy]});
}
}
}
return -1;
}
void Input_data(int n){
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
scanf("%d",&mat[i][j]);
}
}
int main(){
int n;
while(scanf("%d",&n)==1){
Input_data(n);
printf("min=%d\n",BFS(n));
}
}
BFS更改步数法:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N = 100+5;
const int MaxSize = 1e5;
const int INF = (1<<30);
int mat[N][N];
int Min[N][N];
typedef struct node{
int x,y,val;
bool operator < (const node x) const {
return val > x.val;
}
}Node;
const int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int BFS(int n){
priority_queue<Node> Q;
int newx,newy,x=0,y=0,goalx= n-1,goaly=n-1;
Node t,s;
t.x = x,t.y = y,t.val = mat[0][0];
Min[x][y] = mat[x][y];
Q.push(t);
while(true){
t = Q.top();
if(t.x == goalx && t.y == goaly ) return t.val;
for(int d=0;d<4;d++){
newx = t.x+dir[d][0];
newy = t.y+dir[d][1];
if(newx>=0 && newx<n && newy>=0 && newy<n && mat[newx][newy]){
if(t.val + mat[newx][newy] < Min[newx][newy]){
s.x = newx,s.y = newy,s.val = t.val+mat[newx][newy];
Min[newx][newy] = s.val;
Q.push(s);
}
}
}
Q.pop();
}
}
void Init(){
for(int i=0;i<N;i++)
for(int j=0;j<N;j++){
Min[i][j] = INF;
}
}
void Input_data(int n){
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&mat[i][j]);
}
int main(){
int n;
//freopen("1.out","r",stdin);
while(scanf("%d",&n)==1){
Init();
Input_data(n);
printf("min=%d\n",BFS(n));
}
}
建图跑迪杰斯特拉:
#include<iostream>
#include<cstring>
#include<cstdio>
#define _cp(a,b)((a.val)<(b.val))
using namespace std;
const int MAXN = 100000;
const int INF = (1<<30);
const int N = 100 + 5;
int mat[N][N],D[N*N];
bool visit[N*N];
int Size[N*N];
typedef struct node{
short val,to;
}Node;
typedef Node elem_t;
Node edge[N*N][4];
const int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
void Init(){
for(int i=0;i<N*N;i++){
Size[i] = 0;
visit[i] = false;
D[i] = INF;
}
}
void build_mat(int n){
Node t;
int to,newx,newy,from;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
from = i*n+j;
for(int d=0;d<4;d++){
newx = i + dir[d][0];
newy = j + dir[d][1];
if(newx>=0 && newx<n && newy>=0 && newy<n && mat[newx][newy]){
to = newx*n+newy;
int & cnt = Size[from];
t.to = to,t.val=mat[newx][newy];
edge[from][cnt++] = t;
}
}
}
}
struct heap{
elem_t h[MAXN];
int n,p,c;
void init(){n=0;}
void ins(elem_t e){
for(p=++n;p>1 && _cp(e,h[p>>1]);h[p]=h[p>>1],p>>=1);
h[p] = e;
}
int del(elem_t &e){
if(!n) return 0;
for(e=h[p=1],c=2;c<n && _cp(h[c+=(c<n-1 &&_cp(h[c+1],h[c]))],h[n]);h[p] = h[c],p=c,c<<=1);
h[p] = h[n--]; return 1;
}
};
int DIJ(int n){
heap H;
H.init();
D[0] = 0;
Node t;
int u,v;
t.to = 0,t.val = 0;
H.ins(t);
while(H.del(t)){
u = t.to;
visit[u] = true;
if(D[u] < t.val) continue;
for(int j=0; j<Size[u]; j++){
v = edge[u][j].to;
if(visit[v]) continue;
if(D[v] > D[u] + edge[u][j].val){
D[v] = D[u] +edge[u][j].val;
t.to = v,t.val = D[v];
H.ins(t);
}
}
}
return D[n*n-1] + mat[0][0];
}
void Input_data(int n){
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
scanf("%d",&mat[i][j]);
}
}
int main(){
int n;
while(scanf("%d",&n)==1){
Init();
Input_data(n);
build_mat(n);
printf("min=%d\n",DIJ(n));
}
}
双向BFS:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N = 100+5;
const int MaxSize = 1e5;
const int INF = (1<<30);
int mat[N][N];
struct visit{
int val,vis;
}Min[N][N];
typedef struct node{
int x,y,val;
bool operator < (const node x) const {
return val > x.val;
}
}Node;
const int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int BFS(int n){
priority_queue<Node> Q1,Q2;
int newx,newy,cnt,x=0,y=0,goalx= n-1,goaly=n-1,ans = INF;
Node t,s;
t.x = x,t.y = y,t.val = mat[0][0];
s.x = goalx,s.y = goaly,s.val = mat[goalx][goaly];
Min[x][y].vis = 1,Min[x][y].val = mat[x][y];
Min[goalx][goaly].vis = 2,Min[goalx][goaly].val = mat[goalx][goaly];
Q1.push(t);
Q2.push(s);
while(!Q1.empty()|| !Q2.empty()){
cnt = Q1.size();
while(cnt--){
t = Q1.top(); Q1.pop();
if(t.x == goalx && t.y == goaly ) ans = min(ans,t.val); //这里一定要注意,要拓展完才能确定最小值,不能相遇就跳出
for(int d=0;d<4;d++){
newx = t.x+dir[d][0];
newy = t.y+dir[d][1];
if(newx>=0 && newx<n && newy>=0 && newy<n){
if(Min[newx][newy].vis==2) ans = min(t.val + Min[newx][newy].val,ans);
if(t.val + mat[newx][newy] < Min[newx][newy].val){
s.x = newx,s.y = newy,s.val = t.val+mat[newx][newy];
Min[newx][newy].val = s.val;
Min[newx][newy].vis = 1;
Q1.push(s);
}
}
}
}
cnt = Q2.size();
while(cnt--){
t = Q2.top();Q2.pop();
if(t.x == x && t.y == y) return t.val;
for(int d=0;d<4;d++){
newx = t.x + dir[d][0];
newy = t.y + dir[d][1];
if(newx>=0 && newx<n && newy>=0 && newy<n ){
if(Min[newx][newy].vis==1) ans = min(t.val + Min[newx][newy].val,ans);
if(t.val + mat[newx][newy] < Min[newx][newy].val){
s.x = newx,s.y = newy,s.val = t.val + mat[newx][newy];
Min[newx][newy].val = s.val;
Min[newx][newy].vis = 2;
Q2.push(s);
}
}
}
}
}
return ans;
}
void Init(){
for(int i=0;i<N;i++)
for(int j=0;j<N;j++){
Min[i][j].val = INF;
Min[i][j].vis = 0;
}
}
void Input_data(int n){
int val;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
scanf("%d",&val);
mat[i][j] = val?val:INF;
}
}
int main(){
int n;
//freopen("1.out","r",stdin);
while(scanf("%d",&n)==1){
Init();
Input_data(n);
printf("min=%d\n",BFS(n));
}
}
//如有错误,还请指出
在这几种方法里,双向BFS和迪杰斯特拉耗时都是12ms,比其他两种BFS耗时都短,虽然说在这里使用迪杰斯特拉有点大材小用的意味,但是这种方法也去可以应用到其他问题上
搜索专题:问题 E: 挑战ACM迷宫的更多相关文章
- 2015 UESTC 搜索专题A题 王之迷宫 三维bfs
A - 王之迷宫 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/61 Des ...
- HDU(搜索专题) 1000 N皇后问题(深度优先搜索DFS)解题报告
前几天一直在忙一些事情,所以一直没来得及开始这个搜索专题的训练,今天做了下这个专题的第一题,皇后问题在我没有开始接受Axie的算法低强度训练前,就早有耳闻了,但一直不知道是什么类型的题目,今天一看,原 ...
- NOIP2018提高组金牌训练营——搜索专题
NOIP2018提高组金牌训练营——搜索专题 1416 两点 福克斯在玩一款手机解迷游戏,这个游戏叫做”两点”.基础级别的时候是在一个n×m单元上玩的.像这样: 每一个单元有包含一个有色点.我们将用不 ...
- 搜索专题:Balloons
搜索专题:Balloons 这道题一看与时间有关,第一想到的就是BFS,定义一个状态,包含每一个状态的剩余气球数,已经进行的时间和每一个志愿者上一次吹气球的时间: 每一次状态转换时,检查是否有没有使用 ...
- 搜索入门之dfs--经典的迷宫问题解析
今天来谈一下dfs的入门,以前看到的dfs入门,那真的是入门吗,都是把dfs的实现步骤往那一贴,看完是知道dfs的步骤了,但是对于代码实现还是没有概念.今天准备写点自己的心得,真的是字面意思--入门. ...
- 2014 UESTC暑前集训搜索专题解题报告
A.解救小Q BFS.每次到达一个状态时看是否是在传送阵的一点上,是则传送到另一点即可. 代码: #include <iostream> #include <cstdio> # ...
- 2015 UESTC 搜索专题F题 Eight Puzzle 爆搜
Eight Puzzle Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/61 ...
- 2015 UESTC 搜索专题B题 邱老师降临小行星 记忆化搜索
邱老师降临小行星 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/61 Des ...
- 深度优先搜索(DFS),逃离迷宫
[原创] 今天来说说深度优先搜索,深度优先是图论中的内容,大意是从某一点出发,沿着一个方向搜索下去,并伴随着有回退的特点,通常用来判断某一解是否存在,不用来寻找最优解:这里来看一个非常有意思的题目: ...
随机推荐
- luoguP2285 [HNOI2004]打鼹鼠 x
P2285 [HNOI2004]打鼹鼠 题目描述 鼹鼠是一种很喜欢挖洞的动物,但每过一定的时间,它还是喜欢把头探出到地面上来透透气的.根据这个特点阿牛编写了一个打鼹鼠的游戏:在一个n*n的网格中,在某 ...
- idea2018.3.6安装与破解教程(亲测可用、破解到2100年)
最近,帮室友进行idea安装,之前自己安装借鉴的博客已404,在网上找了好几个都无效,想着总结一份备用. 此博客是又找了一台电脑,边安装边写的. 目录 (已安装好的,可以直接看idea2018.3.6 ...
- 【BZOJ4552】排序(线段树,二分)
题意:给定一个n个数的排列,有m次操作:op,l,r op=0时表示将位置[L,R]升序排序 op=1时表示将位置[L,R]降序排序 最后询问第q个位置上的数字 n,m,q<=1e5 思路:Fr ...
- Hadoop监控指标项
配置 修改$HADOOP_HOME/etc/hadoop/hadoop-env.sh # 在配置namenode和datanode时都会有用到JMX_OPTS的代码,是为了减少重复提取出的公共代码 e ...
- python学习之路(7)
调用函数 Python内置了很多有用的函数,我们可以直接调用. 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数.可以直接从Python的官方网站查看文档: http: ...
- 191106DjangoORM之admin数据库管理组件
一.admin数据库管理系统的使用 创建用户 >python manage.py createsuperuser 访问http://127.0.0.1/admin/ app/admin.py 注 ...
- Hadoop之集群搭建
准备 需要准备多台主机(已经安装并且配置好hadoop和jdk) 需要配置ssh免密服务 下面我们开始进行配置,拿到已经准备好的主机,主机名分别为: centos101 centos102 cento ...
- bootstrap 学习笔记(部分)
这个课程中的boostrap是3.0+版本的.(2.0与3.0有区别) bootstrap中的JS是依赖于jquery的,所以需要事先引用jquery(1.9.0版本以上). <!DOCTYPE ...
- c++ 引用& 与 取地址&
https://www.csdn.net/gather_2e/NtjaYgzsNTctYmxvZwO0O0OO0O0O.html 还有指针和取值: int& a = b; int *c = & ...
- leetcode 103二叉树的锯齿形层次遍历
与102相比就增加了flag,用以确定要不要进行reverse操作 reverse:STL公共函数,对于一个有序容器的元素reverse ( s.begin(),s.end() )可以使得容器s的元素 ...