TOJ 432

TOJ 432

題目

https://toj.tfcis.org/oj/pro/432/

有一個 $N \times M$ 的棋盤,在這個棋盤上有 $F$ 個著火的點 $(x_i, y_i)$ 以及一個門 $(u, v)$

現在有個人在 $(x_{me}, y_{me})$ 的位置,每次可以上下左右選擇一個移動一格,請問這個人是否能在不碰到火的情況下走到門的位置

想法

我們可以嘗試從人所在的位置開始,每次走一步,每一個方向都走過,直到找到門或是把全部可行的格子走過,那麼就會知道答案了

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//By Koios1143
#include<iostream>
using namespace std;
int n, m, f, arr[1005][1005], que[1000005][2];
int start_x, start_y, end_x, end_y, cur_x, cur_y, nx, ny;
bool vis[1005][1005], ans=false;

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};

void BFS(){
que[0][0] = start_x;
que[0][1] = start_y;

vis[start_x][start_y] = true;

for(int i=0, j=1 ; i<j ; i++){
cur_x = que[i][0];
cur_y = que[i][1];
// 找到門了
if(cur_x == end_x && cur_y == end_y){
ans=true;
break;
}
// 四個方向都走過
for(int k=0 ; k<4 ; k++){
nx = cur_x + dx[k];
ny = cur_y + dy[k];
// 把超出棋盤的移除
if(nx > n || nx <= 0 || ny <= 0 || ny > m) continue;
if(!vis[nx][ny] && arr[nx][ny] != 1){
vis[nx][ny] = true;
que[j][0] = nx;
que[j][1] = ny;
j++;
}
}
}
}

int main(){
cin>>n>>m;
for(int i=1 ; i<=n ; i++){
for(int j=1 ; j<=m ; j++){
arr[i][j] = 0;
vis[i][j] = false;
}
}
cin>>start_x>>start_y>>end_x>>end_y;
cin>>f;
for(int i=0, x, y ; i<f ; i++){
cin>>x>>y;
arr[x][y] = 1;
}
BFS();
if(ans){
cout<<"Cool!\n";
}
else{
cout<<"Harakiri!\n";
}

return 0;
}

時間複雜度分析

輸入時間複雜度為 $O(nm + f)$

BFS 時間複雜度為 狀態數 $\times$ 操作數量 $= (nm) \times 4$,計為 $O(nm)$

總時間複雜度為 $O(2nm + f)$