2022 CCPC Henan Provincial Collegiate Programming Contest
Problem
Solution
可以发现,每个格子最多被搜索两次,直接进行暴力搜索就行了,但是需要注意:
- 搜索的过程中要标记搜过的点,若不标记,可能会死循环。
- 回溯的时候要注意 “恢复现场”, 即:从当前格子出发,把搜索过的格子再重新标记为未搜索过
Code
const int N = 2e5 + 5, M = 1e6 + 7;
int m, X, Y;
string s[5];
int mp[5][N];
void dfs(int x, int y, int op)
{
if (mp[x][y] || mp[4][Y]) return;
mp[x][y] = 1;
if (x == 4 && y == Y) return;
//1,2, 3, 4 表示从上,右,下,左 进入这个格子
if (op == 1)
{
if (s[x][y] == 'I') dfs(x + 1, y, 1);
else
{
dfs(x, y - 1, 2);
dfs(x, y + 1, 4);
}
}
else if (op == 2)
{
if (s[x][y] == 'I') dfs(x, y - 1, 2);
else
{
dfs(x - 1, y, 3);
dfs(x + 1, y, 1);
}
}
else if (op == 3)
{
if (s[x][y] == 'I') dfs(x - 1, y, 3);
else
{
dfs(x, y - 1, 2);
dfs(x, y + 1, 4);
}
}
else
{
if (s[x][y] == 'I') dfs(x, y + 1, 4);
else
{
dfs(x - 1, y, 3);
dfs(x + 1, y, 1);
}
}
mp[x][y] = 0;//此处特别注意
}
int main()
{
IOS;
int T; cin >> T;
while (T--)
{
cin >> m >> X >> Y;
cin >> s[2] >> s[3];
s[2] = " " + s[2];
s[3] = " " + s[3];
//将越界后的第一个格子标记为搜索过的点
for (int i = 0; i <= m + 1; i++)
{
mp[1][i] = mp[4][i] = 1;
mp[2][i] = mp[3][i] = 0;
}
mp[2][0] = mp[3][0] = mp[2][m + 1] = mp[3][m + 1] = 1;
mp[4][Y] = 0;
dfs(2, X, 1);
if (mp[4][Y]) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}