随便水篇题解:
定义一个 d p [ i ] [ 2 ] dp[i][2] dp[i][2]数组
显然我们向右走时如果是 RLRLRL 交替形式呢么能一直走下去,并且也可以原路返回
我们向左走时如果是 LRLRLR 交替,也可以一直走下去,并且原路返回
样例:
LRRRLL
绘制成图:
0 < − − 1 − − > 2 − − > 3 − − > 4 < − − 5 < − − 6 0<--1-->2-->3-->4<--5<--6 0<−−1−−>2−−>3−−>4<−−5<−−6
我们先求 d p [ i ] [ 0 ] dp[i][0] dp[i][0]数组可以发现 我们不需要考虑 6 点,所以我们下标从1 开始,所以把 6 点映射为 7 点,所以此时 d p [ 7 ] [ 1 ] = 1 dp[7][1]=1 dp[7][1]=1
做出下表:
s: | L | R | R | R | L | L | ||
---|---|---|---|---|---|---|---|---|
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
dp[i][0] | 1 | 2 | 2 | 3 | 1 | 1 | 1 |
可得下面的转移方程:
dp[n + 1][0] = 1;
for (int i = n; i >= 1; i--) {
if (s[i] == 'R' && s[i + 1] == 'L')
dp[i][0] = dp[i + 2][0] + 2;
else if (s[i] == 'R') {
dp[i][0] = 2;
} else {
dp[i][0] = 1;
}
}
我们再求 d p [ i ] [ 1 ] dp[i][1] dp[i][1]数组可以发现 我们不需要考虑 0 点,所以我们下标从0 开始了,所以把 1 点映射为 0 点,所以此时 d p [ 0 ] [ 1 ] = 1 dp[0][1]=1 dp[0][1]=1
做出下表:
s: | L | R | R | R | L | L | ||
---|---|---|---|---|---|---|---|---|
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
dp[i][1] | 1 | 2 | 1 | 1 | 1 | 3 | 2 |
可得下面的转移方程:
dp[0][1] = 1;
for (int i = 1; i <= n; i++) {
if (s[i] == 'L' && s[i - 1] == 'R') {
dp[i][1] = dp[i - 2][1] + 2;
} else if (s[i] == 'L') {
dp[i][1] = 2;
} else {
dp[i][1] = 1;
}
}
然后对两边的答案进行相加去重即可
代码
#include
using namespace std;
typedef long long ll;
struct node {
ll a, b, c;
} p[100005];
int dp[300005][2];
char s[300005];
int main() {
int t;
cin >> t;
for (int _ = 0; _ < t; _++) {
int n;
cin >> n;
cin >> (s + 1);
dp[n + 1][0] = 1;
for (int i = n; i >= 1; i--) {
if (s[i] == 'R' && s[i + 1] == 'L')
dp[i][0] = dp[i + 2][0] + 2;
else if (s[i] == 'R') {
dp[i][0] = 2;
} else {
dp[i][0] = 1;
}
}
dp[0][1] = 1;
for (int i = 1; i <= n; i++) {
if (s[i] == 'L' && s[i - 1] == 'R') {
dp[i][1] = dp[i - 2][1] + 2;
} else if (s[i] == 'L') {
dp[i][1] = 2;
} else {
dp[i][1] = 1;
}
}
for (int i = 0; i <= n; i++) {
cout << dp[i][1] + dp[i + 1][0] - 1 << ' ';
}
puts("");
}
return 0;
}