前言
题解
有一道分层BFS(传火之路)出的不错, 一道0-1字符串思维题(狠狠地对字符串做你想做的事吧)不错。
传火之路
难度: 钻石
思路: 分层BFS
非常好的一道题,但是题意描述有些地方不够准确和严谨
感觉如下改造题意,效果会更好
第一次进入燃火点,一定会触发传送技能,之后燃火点,变为普通点
- case补充
输入
.S@P
..#.
...#
...@
输出
6
这题其实有两个阶段,第一阶段未使用技能,第二阶段使用过技能
所以扩充状态 d p [ y ] [ x ] [ s ] , s ∈ ( 0 , 1 ) , 0 表示没用过技能, 1 表示用过技能 dp[y][x][s], s\in(0, 1),0表示没用过技能,1表示用过技能 dp[y][x][s],s∈(0,1),0表示没用过技能,1表示用过技能
然后跑一边分层BFS即可
当然也有其他解法
- 起始点出发BFS
- 终点出发BFS
两次BFS结合,本质上也是分层BFS,只是分层BFS更通用
#include <bits/stdc++.h>
using namespace std;
int main() {
int h, w;
cin >> h >> w;
vector<string> g(h);
vector<array<int, 2>> ps;
int sy = 0, sx = 0;
int dy = 0, dx = 0;
for (int i = 0; i < h; i++) {
cin >> g[i];
for (int j = 0; j < w; j++) {
if (g[i][j] == 'S') {
sy = i;
sx = j;
} else if (g[i][j] == '@') {
ps.push_back({i, j});
} else if (g[i][j] == 'P') {
dy = i;
dx = j;
}
}
}
int inf = 0x3f3f3f3f;
deque<array<int, 3>> deq;
// 分层状态 dp[h][w][2]
vector<vector<vector<int>>> dp(h, vector<vector<int>>(w, vector<int>(2, inf)));
deq.push_back({sy, sx, 0});
dp[sy][sx][0] = 0;
int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
while (!deq.empty()) {
auto p = deq.front();
deq.pop_front();
int y = p[0], x = p[1], s = p[2];
if (g[y][x] == '@' && s == 0) {
for (auto &step: ps) {
if (step[0] == y && step[1] == x) continue;
if (dp[step[0]][step[1]][1] > dp[y][x][0]) {
dp[step[0]][step[1]][1] = dp[y][x][0];
deq.push_back({step[0], step[1], 1});
}
}
} else {
for (int i = 0; i < 4; i++) {
int ty = y + dir[i][0];
int tx = x + dir[i][1];
if (ty >= 0 && ty < h && tx >= 0 && tx < w) {
if (g[ty][tx] == '#') continue;
if (dp[ty][tx][s] > dp[y][x][s] + 1) {
dp[ty][tx][s] = dp[y][x][s] + 1;
deq.push_back({ty, tx, s});
}
}
}
}
}
int r = min(dp[dy][dx][0], dp[dy][dx][1]);
cout << (r == inf ? -1 : r) << endl;
return 0;
}
狠狠地对字符串做你想做的事吧
难度:黄金
题型: 思维题 + 找规律
可以发现,如果末尾为x的字符串, 最终能变为 x+ 的形态
如果要变成一个字符长,则需要x的相反字符去消除x+
-
以01,10结尾的子串,都可以最终变成一个字符的形态
-
单独的一个字符子串
枚举子数组的右端点,然后累加计算即可
#include <bits/stdc++.h>
using namespace std;
long long solve(int n, const string &s) {
long long res = 1;
for (int i = 1; i < n; i++) {
if (s[i - 1] != s[i]) {
res += (i + 1);
} else {
res += 1;
}
}
return res;
}
int main() {
int t;
cin >> t;
while (t-- > 0) {
int n;
string s;
cin >> n >> s;
cout << solve(n, s) << endl;
}
return 0;
}