JZYZOJ1442 [noip2013]华容道 bfs 最短路 剪枝

http://172.20.6.3/Problem_Show.asp?id=1442

想到最短路的简直神了,如果我写我大概只能写一个30分的bfs。

从数据范围可以看出思路是bfs剪枝,但这里的剪枝是通过最短路的预处理实现的。

设需要移动的格子为a格子。

对求最小移动数有意义的移动只有两种,一种是空白格子的移动,一种是a格子移动到空白格子里。

可以得知要把空白格子移动到a格子旁边然后对a格子进行移动。

那么我们有了每次查找时进行的预处理1:求空白格子到a格子四周格子的最短路。

在模拟移动的过程中,可以发现a格子移动的方向是由其旁边的空白格子的位置决定的,对改变a格子移动方向有意义的步数是改变空白格子相对于a格子的方向的步数。

所以我们就有了预处理2:在查找前预处理出loc[x][y][i][j],即空白格子从格子(x,y)的i方向移动到j方向的最短路。

需要注意的是,预处理1中求最短路是不能经过a格子所在位置的,同样,其他的bfs或最短路处理也要注意格子移动对所求格子位置的改变,避免改变所求格子位置的情况。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 using namespace std;
  8 const long long modn=1000000007;
  9 int n,m,d;
 10 int e[40][40]={};
 11 int dis[40][40]={};
 12 int an[40][40][4]={};
 13 int loc[40][40][4][4]={};
 14 int vis[40][40][4]={};
 15 int d1[4]={0,0,1,-1};
 16 int d2[4]={1,-1,0,0};
 17 int ex,ey,sx,sy,tx,ty,ma;
 18 struct pa{
 19     int x;
 20     int y,w;
 21 };
 22 void getit(int xx,int yy){
 23     int x,y;
 24     queue<pa>q;
 25     pa z;
 26     for(int i=0;i<4;i++){
 27         z.x=xx+d1[i];
 28         z.y=yy+d2[i];
 29         memset(dis,63,sizeof(dis));
 30         if(e[z.x][z.y]){
 31             dis[z.x][z.y]=0;
 32             q.push(z);
 33         }
 34         while(!q.empty()){
 35             x=q.front().x;y=q.front().y;q.pop();
 36             for(int i=0;i<4;i++){
 37                 z.x=x+d1[i];
 38                 z.y=y+d2[i];
 39                 if(e[z.x][z.y]&&(z.x!=xx||z.y!=yy)&&dis[z.x][z.y]==ma){
 40                     dis[z.x][z.y]=dis[x][y]+1;
 41                     q.push(z);
 42                 }
 43             }
 44         }
 45         for(int j=0;j<4;j++){
 46             int xx1,yy1;
 47             xx1=xx+d1[j];
 48             yy1=yy+d2[j];
 49             loc[xx][yy][i][j]=dis[xx1][yy1];
 50         }
 51     }
 52 }
 53 void pre(){
 54     pa z;
 55     queue<pa>q;
 56     memset(dis,63,sizeof(dis));
 57     dis[ex][ey]=0;
 58     z.x=ex;
 59     z.y=ey;
 60     q.push(z);
 61     int x,y;
 62     while(!q.empty()){
 63         x=q.front().x;y=q.front().y;q.pop();
 64         for(int i=0;i<4;i++){
 65             z.x=x+d1[i];
 66             z.y=y+d2[i];
 67             if(e[z.x][z.y]&&(z.x!=sx||z.y!=sy)&&dis[z.x][z.y]==ma){
 68                 dis[z.x][z.y]=dis[x][y]+1;
 69                 q.push(z);
 70             }
 71         }
 72     }
 73 }
 74 int bfs(){
 75     if(sx==tx&&sy==ty)return 0;
 76     pre();
 77     queue<pa>q;pa z;
 78     memset(an,63,sizeof(an));
 79     for(int i=0;i<4;i++){
 80         z.x=sx+d1[i];
 81         z.y=sy+d2[i];
 82         z.w=i;
 83         if(e[z.x][z.y]&&dis[z.x][z.y]!=ma){
 84             an[sx][sy][i]=dis[z.x][z.y];
 85             z.x=sx;z.y=sy;
 86             vis[sx][sy][i]=1;
 87             q.push(z);
 88         }
 89     }int x,y,w;
 90     while(!q.empty()){
 91         x=q.front().x;
 92         y=q.front().y;
 93         w=q.front().w;
 94         q.pop();
 95         for(int i=0;i<4;i++){
 96             if(i==w)continue;
 97             z.x=x;z.y=y;z.w=i;
 98             if(e[x+d1[w]][y+d2[w]]&&an[x][y][w]+loc[x][y][w][i]<an[x][y][i]){
 99                 an[x][y][i]=an[x][y][w]+loc[x][y][w][i];
100                 if(!vis[x][y][i]){
101                     vis[x][y][i]=1;
102                     q.push(z);
103                 }
104             }
105         }
106         z.x=x+d1[w];z.y=y+d2[w];
107         if(w==0)z.w=1;
108         else if(w==1)z.w=0;
109         else if(w==2)z.w=3;
110         else z.w=2;
111         if(an[x][y][w]+1<an[z.x][z.y][z.w]){
112             an[z.x][z.y][z.w]=an[x][y][w]+1;
113             if(!vis[z.x][z.y][z.w]){
114                 vis[z.x][z.y][z.w]=1;
115                 q.push(z);
116             }
117         }
118         vis[x][y][w]=0;
119     }
120     int ans=ma;
121     for(int i=0;i<4;i++){
122         ans=min(ans,an[tx][ty][i]);
123     }
124     if(ans!=ma)return ans;
125     return -1;
126 }
127 int main(){
128     //freopen("wtf.in","r",stdin);
129     scanf("%d%d%d",&n,&m,&d);
130     for(int i=1;i<=n;i++){
131         for(int j=1;j<=m;j++){
132             scanf("%d",&e[i][j]);
133         }
134     }memset(loc,63,sizeof(loc));
135     ma=loc[1][1][1][1];
136     for(int i=1;i<=n;i++){
137         for(int j=1;j<=m;j++){
138             getit(i,j);
139         }
140     }
141     for(int i=1;i<=d;i++){
142         scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
143         memset(vis,0,sizeof(vis));
144         printf("%d\n",bfs());
145     }
146     return 0;
147 }

时间: 2024-11-09 18:13:00

JZYZOJ1442 [noip2013]华容道 bfs 最短路 剪枝的相关文章

uva11624 fire bfs 最短路

// uva11624 bfs最短路 // Fire 给你一个图,有一个起点'J',从任何边界走出去就算成功 // 但是,会有起火的地方,每秒火会上下左右四个方向蔓延,人不能 // 走有火的地方,问能不能逃出去,逃出去的最少步数是多少 // // 我的思路就是先预处理出每个地方的火的燃烧的最开始的时间 // 这bfs就可以了,计为f[i][j]; // 之后的再走一遍最短路,用s[i][j]记录人所能达到的最早的时间 // 走不到为-1,则,最后只要判断边界上能走到的就ok了 // 优化就是当走

BZOJ 1698 [Usaco2007 Feb]Lilypad Pond 荷叶池塘 BFS+最短路

题意:链接 **方法:**BFS+最短路 解析: 这道题还是挺有意思的. 第一个想法被卡,第一发是二分+bfs,但是这样的话,会有什么处理不了呢?到一个点的流量. 所以就得换想法. 不妨重新定义最短路. 把图中所有的0的点看做可行点,每一次搜出从该点可以到打的0点,然后将这个边权视作1. 即f[i][j]代表到i,j这点的最短路. 显然终点特判: 然后同时记录一下最短路的数量即可. 代码: #include <queue> #include <cstdio> #include &l

hdu 4400 离散化+二分+BFS(暴搜剪枝还超时的时候可以借鉴一下)

Mines Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1110    Accepted Submission(s): 280 Problem Description Terrorists put some mines in a crowded square recently. The police evacuate all peo

题解——逃离僵尸岛(BFS+最短路+虚拟节点)

题解--逃离僵尸岛(BFS+最短路+虚拟节点) 一道很巧妙的最短路问题,细节也要注意 题面 Description 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被僵尸控制了,如果贸然闯入就会被感染TAT...所以不能进入.由其中任意城市经过不超过S条道路就可以到达的别的城市,就是危险城市.换句话说只要某个没有被占城市到某个被占城市不超过s距离,就是危险. 小a住在1号城市,国际

NOIP2013 提高组day2 3 华容道 BFS

描述 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间. 小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的: 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的: 有些棋子是固定的,有些棋子则是可以移动的: 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白

[noip2013][codevs3290]华容道 bfs+spfa

const u:array[1..4] of integer=(-1,0,1,0); v:array[1..4] of integer=(0,1,0,-1); oo=100000000; type node=record x,y,cs,l:longint; end; var ft:text; n,m,q,ii,i,i1,j1,j,l,w,x,y,x1,y1,x2,y2,x3,y3,es,ey,wei,tou,kx,ky,ans:longint; r:array[0..5000000] of no

Uva 1600 Patrol Robot (BFS 最短路/DFS剪枝)

这道题运用的知识点是求最短路的算法.一种方法是利用BFS来求最短路. 需要注意的是,我们要用一个三维数组来表示此状态是否访问过,而不是三维数组.因为相同的坐标可以通过不同的穿墙方式到达. #include <bits/stdc++.h> using namespace std; struct Node{ int r; int c; int g; int cnt; Node(int r,int c,int g,int cnt):r(r),c(c),g(g),cnt(cnt){} }; int v

[RT][NOIP2013]华容道

1.题面 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间.小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的: 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的: 有些棋子是固定的,有些棋子则是可以移动的: 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空

noip2013 华容道

P1979 华容道 131通过 471提交 题目提供者该用户不存在 标签图论搜索/枚举2013NOIp提高组 难度省选/NOI- 提交该题 讨论 题解记录 最新讨论 要注意部分数据存在起点与终… 求助求助求助 题目数据是不是有问题啊 题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的: 在一