---
# System prepended metadata

title: Week 11 BFS

---

# Week 11 BFS

:::info
時間：04/30 9:00 ~ 17:00
地點：成大資工系新館 **65304** 教室
主題：BFS
直播連結：https://youtube.com/live/QdZruoWnPZo?feature=share
:::

# 必作題題解

[TOC]

## 三章_第二節

### TOJ 432 - Akechi 明智的選擇

撰寫：fishhh

這裡改用 BFS 來解，就 BFS 的裸題

:::spoiler
```cpp=
#include<iostream>
using namespace std;
int move_x[]={0,0,-1,1},move_y[]={1,-1,0,0};
int a,b,n,m,map[1002][1002]={},u,v,f;
void bfs(int pos_x,int pos_y,int sum){
    if(map[pos_x][pos_y]==-1){
        return ;
    }
    if(map[pos_x][pos_y]==0){
        map[pos_x][pos_y]=sum;
        int nx,ny;
        for(int i=0;i<4;i++){
            nx=pos_x+move_x[i];
            ny=pos_y+move_y[i];
            if(nx<1||ny<1||nx>n||ny>m){
                continue;
            }
            bfs(nx,ny,sum+1);
        }
    }
}
int main(){
    int x,y;
    cin>>n>>m>>x>>y>>u>>v>>f;
    for(int i=0;i<f;i++){
        cin>>a>>b;
        map[a][b]=-1;
    }
    bfs(x,y,0);
    if(map[u][v]==0){
        cout<<"Harakiri!\n";
    }
    else{
        cout<<"Cool!\n";
    }
}
```
:::



---

### UVa 439 - Knight Moves

撰寫：fishhh

這裡比較不一樣的是處理騎士走路的問題。主要就是 dx 和 dy 陣列比較不同。

:::spoiler
```cpp=
#include "iostream"
#include "queue"
using namespace std;
int main(){
    string x,y;
    while(cin>>x>>y){
        queue<pair<int,int>> q;
        int ans[10][10]={};
        bool vis[10][10]={};
        int tar_x=y[0]-'a',tar_y=y[1]-'0';
        tar_x++;
        int np_x=x[0]-'a',np_y=x[1]-'0';
        np_x++;
        int cx[]={-2,-1,1,2,2,1,-1,-2},cy[]={-1,-2,2,1,-1,-2,2,1};
        int nst=0;
        q.push({np_x,np_y});
        vis[np_x][np_y]=1;
        ans[np_x][np_y]=0;
        while(!q.empty()){
            int nl=q.size();
            for(int i=0;i<nl;i++){
                auto np=q.front();
                q.pop();
                ans[np.first][np.second]=nst;
                if(np.first==tar_x&&np.second==tar_y){
                    while(q.size())q.pop();
                    break;
                }
                for(int x=0;x<8;x++){
                    int nx=np.first+cx[x],ny=np.second+cy[x];
                    if(nx<=0||ny<=0||nx>=9||ny>=9)continue;
                    if(!vis[nx][ny]){
                        q.push({nx,ny});
                        vis[nx][ny]=1;
                    }
                }
            }
            nst++;
        }
        printf("To get from %s to %s takes %d knight moves.\n",x.c_str(),y.c_str(),nst-1);
    }
}
```
:::

---

### UVa 532 - Dungeon Master

撰寫：fishhh

這題比較不同的就是地圖變成3維了，其餘操作都相同。
可以練一下實作的能力~

:::spoiler
```cpp=
#include<queue>
#include<iostream>
using namespace std;
struct node{
	int x;
	int y;
	int z;	
};
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int l,r,c;
	string str;
	int map[40][40][40],el,er,ec;
	while(cin>>l>>r>>c){
		if(l==0&&r==0&&c==0){
			return 0;
		}
		queue<node> q;
		node tmp,now;
		bool vis[40][40][40]={};
		for(int il=0;il<l;il++){
			for(int ir=0;ir<r;ir++){
				cin>>str;
				for(int ic=0;ic<c;ic++){
					if(str[ic]=='#'){
						map[ic][ir][il]=-1;
						vis[ic][ir][il]=1;
					}
					else if(str[ic]=='.'){
						map[ic][ir][il]=0;
					}
					else if(str[ic]=='S'){
						map[ic][ir][il]=0;
						tmp.x=ic;
						tmp.y=ir;
						tmp.z=il;	
						vis[ic][ir][il]=1;
						q.push(tmp);
					}
					else{
						map[ic][ir][il]=0;
						el=il,er=ir,ec=ic;
					}
				}
			}
		}
		//input end
		int time=0,cx[]={0,0,-1,1},cy[]={-1,1,0,0};
		while(!q.empty()){
			int nl=q.size();
			for(int inl=0;inl<nl;inl++){
				node nxt;
				now=q.front();
				q.pop();
				nxt=now;
				if(map[now.x][now.y][now.z]==-1){
					continue;
				}
				map[now.x][now.y][now.z]=time;
				if(nxt.z-1>=0){
					nxt.z--;
					if(!vis[nxt.x][nxt.y][nxt.z]){
						vis[nxt.x][nxt.y][nxt.z]=1;
						q.push(nxt);	
					}
					nxt.z++;
				}
				if(nxt.z+1<l){
					nxt.z++;
					if(!vis[nxt.x][nxt.y][nxt.z]){
						vis[nxt.x][nxt.y][nxt.z]=1;
						q.push(nxt);	
					}
					nxt.z--;
				}
				for(int i=0;i<4;i++){
					nxt.x=now.x+cx[i],nxt.y=now.y+cy[i],nxt.z=now.z;
					if(nxt.x<0||nxt.y<0||nxt.x>=c||nxt.y>=r){
						continue;
					}
					if(!vis[nxt.x][nxt.y][nxt.z]){
						vis[nxt.x][nxt.y][nxt.z]=1;
						q.push(nxt);
					}
				}	
			}
			time++;
		}
//		for(int il=0;il<l;il++){
//			for(int ir=0;ir<r;ir++){
//				for(int ic=0;ic<c;ic++){
//					cout<<map[ic][ir][il]<<" ";
//				}
//				cout<<"\n";
//			}
//			cout<<"\n";
//		}
		if(map[ec][er][el]!=0){
			cout<<"Escaped in "<<map[ec][er][el]<<" minute(s).\n";
		}
		else{
			cout<<"Trapped!\n";
		}
	}
}
```
:::



---

### UVa 10102 - The path in the colored field

撰寫：fishhh

一開始可能會想說，對於每一個 1 做 BFS 找最短路。
分析一下複雜度，做一次 BFS 的時間是 $O(n^2)$ 然後最多有可能做 $O(n^2)$ (因為最多有 $n^2$ 個 1)
整體就是 $O(n^4)$ 接近 $10^8$ 雖然常數不大 但很可能 TLE。

又有另一個想法，把所有 1 跟 3 的座標抓出來，然後對於每個 1 去掃過一次所有 3 的座標( x,y 座標差就是他們之間最短距離! ) 就可以知道對於一個 1 的位置與 3 的最短距離!
然後全部的 1 都做一次然後取最大值，就可以知道答案了~

分析複雜度，最壞的情況有 $(n^2)/2$ 個 1 有 $(n^2)/2$ 個 3 (這樣乘起來才會盡量大)，所以複雜度會是 $O(n^4)$ 但嚴格來說這個會快一點點啦XD。


其實實際上還是跟找最短路徑一樣，反正就是把所有起點都 push 進 queue 裡面，然後做一次 BFS 就好~

:::spoiler
```cpp=
#include<bits/stdc++.h>
using namespace std;

struct Node {
    int x, y, dis;
};

char board[110][110];
bool used[110][110];
Node q[2000000];
int m, dx[4]={0,1,0,-1}, dy[4]={1,0,-1,0};

int bfs(int start_y, int start_x) {
    Node current, next;
    memset(used, false, sizeof(used));
    q[0].y = start_y;
    q[0].x = start_x;
    q[0].dis = 0;

    for (int i = 0, j = 1; i < j; i++) {
        current = q[i];

        if (board[current.y][current.x] == '3') {
            return current.dis;
        } else {
            for (int k = 0; k < 4; k++) {
                next = current;
                next.x += dx[k];
                next.y += dy[k];
                next.dis++;

                if (next.x >= 0 && next.x < m && next.y >= 0 && next.y < m) {
                    if (!used[next.y][next.x]) {
                        used[next.y][next.x] = true;
                        q[j] = next;
                        j++;
                    }
                }
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    while (cin >> m) {
        vector<int> distances;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                cin >> board[i][j];
            }
        }

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                if (board[i][j] == '1') {
                    distances.push_back(bfs(i, j));
                }
            }
        }

        sort(distances.begin(), distances.end());
        cout << distances.back() << "\n";
    }

    return 0;
}

```
:::

---



