CF585B Phillip and Trains
题意:
给定一个 .
。现在有一个起点,字符表示为 s
,每次 s
先向右走一格,然后可以选择向上向下或不变位置。之后每一列火车会向左行驶两格。问有没有方法使得从起点开始不被火车撞死到达任意一行最后一列。
解法:
这题用搜索解决。因为问题是连通性而非最小步数等问题,广搜深搜均可解决。但是特别要注意的地方是存储火车以及火车向左行驶两步的模拟。
我们考虑用一个结构体存储一列火车的信息,那么我们需要存储的是这列火车所在的行,火车最左端与最右端所在的列,总共
struct Node
{
int l, r, x; // 左端点所在的列、右端点所在的列、火车所在的行
Node(int a, int b, int c): l(a), r(b), x(c){} // 构造函数
Node()
{
l = r = x = 0;
} // 构造函数
};
处理字符串时我们可以用 vector
存储每列火车,用 unordered_map
记录每列火车是否以及存储,因为题面说相同的火车字符相同。
剩下的问题在于火车行驶的模拟,这里有一个细节,例如以下例子:
1
6 1
s...AA
....BB
....CC
那么其中一种方案的下一步是:
..AA..
.sBB..
..CC..
紧接着是:
AA....
BBs...
CC....
但是很明显最后这个状态无法实现,因为在 s
转移时会被火车撞到。但是如果直接模拟那么转移后其实是合法的,但是转移过程不合法。所以一定要对转移过程特判。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <utility>
#include <unordered_map>
#include <vector>
using namespace std;
const int N = 105;
string s[N];
int t, n, k;
bool f[N][N];
struct Node
{
int l, r, x;
Node(int a, int b, int c): l(a), r(b), x(c){}
Node()
{
l = r = x = 0;
}
};
vector<Node> train; // 保存火车
unordered_map<char, bool> mp;
inline bool check(int x, int y)
{
for (int i = 0; i < train.size(); i++)
{
if (train[i].x == x && train[i].l <= y && train[i].r >= y)
{
return true;
}
}
return false;
}
inline bool work_next(int x, int y)
{
for (int i = 0; i < train.size(); i++)
{
if (train[i].x == x && train[i].l <= y && train[i].r >= y) return true;
if (train[i].x == x && train[i].l - 2 <= y && train[i].r >= y) return true;
}
for (int i = 0; i < train.size(); i++)
{
train[i].l -= 2;
train[i].r -= 2;
}
return false;
}
inline void work_pre()
{
for (int i = 0; i < train.size(); i++)
{
train[i].l += 2;
train[i].r += 2;
}
}
inline bool dfs(int x, int y)
{
if (x < 1 || x > 3 || y < 0 || y >= n || f[x][y] || check(x, y)) return false;
f[x][y] = true;
if (y == n - 1)
{
//cout << x << " " << y << endl;
puts("YES");
return true;
}
y++;
if (check(x, y)) return false;
if (!work_next(x, y))
{
if (dfs(x, y)) return true;
work_pre();
}
if (!work_next(x - 1, y))
{
if (dfs(x - 1, y)) return true;
work_pre();
}
if (!work_next(x + 1, y))
{
if (dfs(x + 1, y)) return true;
work_pre();
}
return false;
}
int main()
{
scanf("%d", &t);
while (t--)
{
memset(f, false, sizeof(f));
scanf("%d %d", &n, &k);
train.clear();
mp.clear();
int sx = 0, sy = 0;
for (int i = 1; i <= 3; i++)
{
cin >> s[i];
}
for (register int i = 1; i <= 3; i++)
{
for (register int j = 0; j < n; j++)
{
if (s[i][j] == 's')
{
sx = i;
sy = j;
}
else
{
if (s[i][j] == '.' || mp.count(s[i][j])) continue;
mp[s[i][j]] = true;
Node p;
p.x = i;
p.l = j;
p.r = j;
for (register int k = j + 1; k < n; k++)
{
if (s[i][k] != s[i][j])
{
p.r = k - 1;
break;
}
}
train.push_back(p);
}
}
}
if (!dfs(sx, sy))
{
puts("NO");
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现