洛谷P2346 四子连棋 题解 迭代加深搜索
题目链接:https://www.luogu.com.cn/problem/P2346
首先需要注意 题目描述 中说道的这句话:
黑白双方交替走棋,任意一方可以先走
然后我这边用的是迭代加深搜索解决的这个问题。
我觉得 迭代加深搜索 结合了 DFS 和 BFS 的优点:
- 能够像BFS一样进行层次遍历;
- 使用回溯,相比BFS将所有状态都加入队列,迭代加深搜索更省空间。
示例代码:
#include <bits/stdc++.h>
using namespace std;
char maze[5][5];
inline bool in_map(int x, int y) {
return x >= 0 && x < 4 && y >= 0 && y < 4;
}
int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 }, D;
void test(int d) {
static int cnt = 0;
cnt ++;
// if (cnt % 10 == 0) _sleep(1000 * 100);
cout << d << " :" << endl;
for (int i = 0; i < 4; i ++) cout << maze[i] << endl;
}
bool check() { // 用于判断是否已存在合法状态
for (int i = 0; i < 4; i ++) {
bool flag = true;
for (int j = 1; j < 4; j ++) { // 同一行
if (maze[i][j] != maze[i][0]) {
flag = false;
break;
}
}
if (flag) return true;
flag = true;
for (int j = 1; j < 4; j ++) { // 同一列
if (maze[j][i] != maze[0][i]) {
flag = false;
break;
}
}
if (flag) return true;
}
bool flag = true;
for (int i = 1; i < 4; i ++) { // 对角线
if (maze[i][i] != maze[0][0]) {
flag = false;
break;
}
}
if (flag) return true;
flag = true;
for (int i = 1; i < 4; i ++) { // 斜对角线
if (maze[i][3-i] != maze[0][3]) {
flag = false;
break;
}
}
if (flag) return true;
return false;
}
bool go_check(int d, int x, int y) { // 第奇数步必须走黑子,偶数步必须走白子
if (d % 2) return maze[x][y] == 'B';
else return maze[x][y] == 'W';
}
bool dfs(int d, int delta) {
// test(d);
if (d > D) return check();
for (int x = 0; x < 4; x ++) {
for (int y = 0; y < 4; y ++) {
if (maze[x][y] == 'O') {
for (int i = 0; i < 4; i ++) {
int xx = x + dir[i][0], yy = y + dir[i][1];
if (in_map(xx, yy) && go_check(d+delta, xx, yy)) {
swap(maze[x][y], maze[xx][yy]);
if (dfs(d+1, delta)) return true;
swap(maze[x][y], maze[xx][yy]);
}
}
}
}
}
return false;
}
void handle() {
for (D = 0; ; D ++) {
// cout << "D = " << D << "..." << endl;
if (dfs(1, 0) || dfs(1, 1)) break;
}
}
int main() {
for (int i = 0; i < 4; i ++) scanf("%s", maze[i]);
handle();
printf("%d\n", D);
return 0;
}