1. 程式人生 > >洛谷 P1011

洛谷 P1011

題目描述 給一n \times nn×n的字母方陣,內可能蘊含多個“yizhong”單詞。單詞在方陣中是沿著同一方向連續擺放的。擺放可沿著 88 個方向的任一方向,同一單詞擺放時不再改變方向,單詞與單詞之間可以交叉,因此有可能共用字母。輸出時,將不是單詞的字母用*代替,以突出顯示單詞。例如: 在這裡插入圖片描述 輸入輸出格式 輸入格式: 第一行輸入一個數nn。(7 \le n \le 1007≤n≤100)。

第二行開始輸入n \times nn×n的字母矩陣。

輸出格式: 突出顯示單詞的n * n矩陣。 在這裡插入圖片描述 題解: 這道題目顯然是要用到搜尋。把整個圖全部搜尋一遍,合適的字串標記一下,然後呢。再依據自己的標記陣列把答案輸出出來。我一開始想到用到DFS來進行搜尋,但是我遇到一個難題:如何確定字串是符合題意的?當自己確定一個字串是符合題意的我又如何回過頭把他們全部都標記出來?要是確定一個字母就標記一個字母的話,這樣就全部就錯了,因為你不知道這個你正在搜尋的路徑下這個字串是否是符合題意的。我一開始想到用回溯,但是因為不太會,也不太理解回溯。就沒有寫出來。但是之後看了巨巨的題解,用了第一種方法寫了出來。 就是剛開始就用 i 來記錄這是第 i 步的行走到的座標,每走一步就判斷一下這一步的字元,還有座標是否符合條件,如果不符合就 break 。否則繼續進行迴圈,當 i = 7 的時候就說明之前的所有字元及座標全部符合條件。之後就定義變數 j ,使 j 從 0 開始直到 6 一個一個的標記一下。

#include <iostream>

using namespace std;

const int maxn = 105;

int d[8][2] = {{1, 1}, {1, -1}, {-1, 1}, {-1. -1}, {1, 0}, {0, 1}, {-1, 0}, {0, -1}};
char cmp[7] = {'y', 'i', 'z', 'h', 'o', 'n', 'g'}; 
int n;

bool mark[maxn][maxn] = {0};
char map[maxn][maxn];

void init() {
	cin >> n;
	for (int i = 1; i <= n; i++) 
		for (int j = 1; j <= n; j++)
			cin >> map[i][j];
} 

void print () {
	int i, j;
	for (i = 1; i <= n; i++) {
		for (j = 1; j <= n; j++) {
			if (mark[i][j]) cout << map[i][j];
			else cout << "*";
		}
		cout << endl;
	}
}

void check(int x, int y) {
	int i, j, k;
	for (k = 0; k < 8; k++) {
		for (i = 1; i <= 6; i++) {
			int nx = x + i * d[k][0];
			int ny = y + i * d[k][1];
			if (nx < 1 || nx > n || ny < 1 || ny > n) break;
			if (map[nx][ny] != cmp[i]) break; 
		}
		if (i == 7) 
			for (j = 0; j <= 6; j++)
				mark[x + d[k][0] * j][y + d[k][1] * j] = 1;
// 這一步等於是把之前組成"yizhong"的字元的座標全部到過來標記了一遍 
	}
}

void solve() {
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (map[i][j] == 'y')
				check(i, j);
}

int main() {
	init();
	solve();
	print();
	return 0;
}