藍橋杯-AB路線(詳細原創)

小程xy發表於2024-05-29

問題描述:

有一個由 N × M 個方格組成的迷宮,每個方格寫有一個字母 A 或者 B。小藍站在迷宮左上角的方格,目標是走到右下角的方格。他每一步可以移動到上下左右相鄰的方格去。

由於特殊的原因,小藍的路線必須先走 K 個 A 格子、再走 K 個 B 格子、再走 K 個 A 格子、再走 K 個 B 格子......如此反覆交替。

請你計算小藍最少需要走多少步,才能到達右下角方格? 注意路線經過的格子數不必一定是 K 的倍數,即最後一段 A 或 B 的格子可以不滿 K 個。起點保證是 A 格子。

例如 K=3 時,以下 3 種路線是合法的:

AAA
AAAB
AAABBBAAABBB

以下 3 種路線不合法:

ABABAB
ABBBAAABBB
AAABBBBBBBAAA

輸入格式

第一行包含三個整數 N、M 和 K。

以下 N 行,每行包含 M 個字元 ( A 或 B ),代表格子型別。

輸出格式

一個整數,代表最少步數。如果無法到達右下角,輸出 -1。

樣例輸入

4 4 2
AAAB
ABAB
BBAB
BAAA

樣例輸出

8

樣例說明

每一步方向如下:下右下右上右下下;路線序列:AABBAABBA。

評測用例規模與約定

對於 20% 的資料,1 ≤ N, M ≤ 4。

對於另 20% 的資料,K=1。

對於 100% 的資料,1 ≤ N, M ≤ 1000,1 ≤ K ≤ 10。

題解:

寬搜bfs題, 用queue佇列按要求搜尋。

但需要注意 正常二維bfs搜尋標記是否訪問過的st陣列用的二維, 但是這題用的st陣列是三維

st含義:

st[x][y][z]: 座標x, y上的字元, 在第z次訪問的時候是否訪問過了

如下圖:
圖中圈起來的B, 當每一步走的是: 下下下下, 此時第一次遍歷到B, st[3][0][0] = true, 然後繼續 下下下右上上上左, 此時又一次遍歷到這個B, st[3][0][2] = true, 最後上右右右下下下下, 到達(n,m)

  • 當第一次遍歷到B的時候st中的z = 0, 因為此時的B位於BBB的第一個
  • 當第二次遍歷到B的時候st中的z = 2, 因為此時的B位於BBB的第三個

如果我們用的還是二維st, 那麼就不可能第二次遍歷到B, 也就找不到答案了

ac程式碼👇

#include <bits/stdc++.h>
using namespace std;
struct Node
{
	int x, y, deep, step;  // deep深度, step是一共走的步數, 初始位置也算一步, deep初始化是0, step初始化是1
};
const int N = 1e3 + 10;
int n, m, k; 
char g[N][N];
bool st[N][N][20];  // 打標記, 看之前是否走過, 防止進入死迴圈
int go[N][N] = {{0, 1}, {0, - 1}, {1, 0}, {-1, 0}};  // 四個方向可以走

int bfs()
{
	queue<Node> q;
	q.push({0, 0, 0, 1}); st[0][0][0] = true; 
	
	while (q.size())
	{
		auto t = q.front();
		q.pop();
		
		if (t.x == n - 1 && t.y == m - 1) return t.deep;  // 找到答案, 返回
		
		for (int i = 0; i < 4; i ++)
		{
			int aa = t.x + go[i][0], bb = t.y + go[i][1], stp = t.step + 1;
			
			if (aa < 0 || aa >= n || bb < 0 || bb >= m) continue;  // 超出邊界, 跳過迴圈
			
			if (stp > k)   // 需要轉換字元
			{
				stp = 1;
				if (g[aa][bb] == g[t.x][t.y]) continue;  // 如果字元跟原來相同, 跳過
			}
			else   // 不需要轉換字元
			{
				if (g[aa][bb] != g[t.x][t.y]) continue;  // 如果字元跟原來不同, 跳過
			}
				
			if (!st[aa][bb][stp])  // 沒有訪問過
			{
				st[aa][bb][stp] = true;
				q.push({aa, bb, t.deep + 1, stp});
			}
		}
	}
	return -1;  // 沒有找到答案, 無解
}

int main()
{
	cin >> n >> m >> k;
	
	for (int i = 0; i < n; i ++) cin >> g[i];
	int res = bfs();
	cout << res << endl;
	return 0;
}

覺得寫的不錯的話, 點個贊吧~