ABC246 E:Bishop 2题解
\text{题目}
原题连接:https://atcoder.jp/contests/abc246/tasks/abc246_e
E - Bishop 2
Time Limit: 6 sec / Memory Limit: 2048 MB
Score : 500 points
Problem Statement
We have an
- If
S_{i,j} =., the square(i,j) is empty. - If
S_{i,j} =#, the square(i,j) is occupied by a white pawn, which cannot be moved or removed. We have put a white bishop on the square(A_x,A_y) .
Find the minimum number of moves needed to move this bishop from -1 instead.
Notes
A white bishop on the square
-
For each positive integer
d , it can go to(i+d,j+d) if all of the conditions are satisfied.- The square
(i+d,j+d) exists in the board. - For every positive integer
l \le d ,(i+l,j+l) is not occupied by a white pawn.
- The square
-
For each positive integer
d , it can go to(i+d,j-d) if all of the conditions are satisfied.- The square
(i+d,j-d) exists in the board. - For every positive integer
l \le d ,(i+l,j-l) is not occupied by a white pawn.
- The square
-
For each positive integer
d , it can go to(i-d,j+d) if all of the conditions are satisfied.- The square
(i-d,j+d) exists in the board. - For every positive integer
l \le d ,(i-l,j+l) is not occupied by a white pawn.
- The square
-
For each positive integer
d , it can go to(i-d,j-d) if all of the conditions are satisfied.- The square
(i-d,j-d) exists in the board. - For every positive integer
l \le d ,(i-l,j-l) is not occupied by a white pawn.
- The square
Constraints
-
2 \le N \le 1500 -
1\le A_x,A_y\le N -
1\le B_x,B_y\le N -
(A_x ,A_y)\ne (B_x ,B_y) -
-
-
Input
Input is given from Standard Input in the following format:
Output
Print the answer.
Sample Input 1
5
1 3
3 5
....#
...#.
.....
.#...
#....
Sample Output 1
3
We can move the bishop from
Sample Input 2
4
3 2
4 2
....
....
....
....
Sample Output 2
-1
There is no way to move the bishop from
Sample Input 3
18
18 1
1 18
..................
.####.............
.#..#..####.......
.####..#..#..####.
.#..#..###...#....
.#..#..#..#..#....
.......####..#....
.............####.
..................
..................
.####.............
....#..#..#.......
.####..#..#..####.
.#.....####..#....
.####.....#..####.
..........#..#..#.
.............####.
..................
Sample Output 3
9
\text{题意简述}
英语好的大佬们应该不用看
给定一个国际象棋中的象及若干个不可移动的障碍物,求象从给定点
\text{题目分析}
为什么这道题没有在题库里?
比较厉害的OIer应该很快就发现这是一道BFS题,可以使用隐式图做法,背过模板精通编程的人可以用BFS走迷宫的模板,当然,CSP或NOIP当天是不会让大家带模板U盘去的(废话)。下面我将给出3种做法。
\text{解法一:BFS}
这是我第一次采用的做法,简单粗暴,直接上代码。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1500+10;
int n,dis[MAXN][MAXN];//n<=1500
bool vis[MAXN][MAXN],blocked[MAXN][MAXN];//两种情况:走不通和已访问分开处理。
char cur;
struct pos{
int x,y;
}s,e,dpos[]={{1,1},{1,-1},{-1,1},{-1,-1}};
bool operator==(pos a,pos b){
return a.x==b.x&&a.y==b.y;
}
queue<pos> q;
queue<pos> get_pos(pos p){//获得下一步能去的节点
queue<pos> retVal;
pos cur=p;
while(!blocked[++cur.x][++cur.y]) if(!vis[cur.x][cur.y]) retVal.push(cur);
cur=p;
while(!blocked[--cur.x][++cur.y]) if(!vis[cur.x][cur.y]) retVal.push(cur);
cur=p;
while(!blocked[++cur.x][--cur.y]) if(!vis[cur.x][cur.y]) retVal.push(cur);
cur=p;
while(!blocked[--cur.x][--cur.y]) if(!vis[cur.x][cur.y]) retVal.push(cur);
return retVal;
}
int main(){
cin>>n;
cin>>s.x>>s.y;
cin>>e.x>>e.y;
for(int i=0;i<=n+1;i++) blocked[0][i]=blocked[i][0]=blocked[n+1][i]=blocked[i][n+1]=true;//边界
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){
cin>>cur;
dis[i][j]=-1;
if(cur=='#') blocked[i][j]=true;
}
vis[s.x][s.y]=true;
dis[s.x][s.y]=0;
q.push(s);
while(!q.empty()){
pos cur=q.front();
q.pop();
queue<pos> nxt=get_pos(cur);
// cout<<cur.x<<" "<<cur.y<<"->"<<endl;
while(!nxt.empty()){
// cout<<nxt.front().x<<" "front().y<<endl;
int x1=nxt.front().x,y1=nxt.front().y;
if(dis[x1][y1]!=-1) return 2147483647;//assert
q.push(nxt.front());//新节点入队
vis[x1][y1]=true;
dis[x1][y1]=dis[cur.x][cur.y]+1;//记录距离
if(nxt.front()==e) break;//如果是目标节点,程序结束
nxt.pop();
}
}
cout<<dis[e.x][e.y];
return 0;
}
注意访问和阻挡要分开考虑。
\text{方法二:BFS}
你没看错,还是BFS。
每一次只走一步,判断对答案有没有贡献。如果这次的方向和上一次相同就有贡献,否则没有。
\text{方法三:deque优化}
在方法二的基础上,如果对答案没有贡献的放在队头,优先考虑。
\text{我的DEBUG日志}
220418 代码完成
220421 找到BUG并调试
|- BUG:访问过和被阻挡放到一起考虑,结果错误。
\- 当天AC