题目大意
给出一个包含F和T的序列,F代表向前走一步,T代表转身(180°)。
必须修改N次序列,修改一次代表将一个位置的F变成T或T变成F,求出修改后的操作序列结束后可以到达的最远距离。
题解
设
fi,j,k,d
为前i个操作结束,修改了j次,当前位置为k(可以为负,所以统一加上总操作数量m以保证为正),方向为d(0代表向前,1代表向后)的状态能否达到。
转移的时候考虑当前位修改还是不修改即可。
注意可以将一位修改多次,那么在最终统计最大值的时候,修改
n
次,
#include<bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for(register int i = (l); i <= (r); i++)
const int N = 100 + 10;
char s[N];
int n, m, f[N][60][N<<1][2];
void init(){
scanf("%s", s + 1);
scanf("%d", &n);
m = strlen(s + 1);
}
void work(){
f[0][0][m][0] = 1;
rep(i, 1, m) rep(j, 0, n) rep(k, 0, (m<<1)) rep(d, 0, 1){
if(s[i] == 'T'){
f[i][j][k][d] |= f[i-1][j][k][d^1];
int tk = k + (d ? 1 : -1);
if(tk >= 0 && tk <= (m<<1) && j)
f[i][j][k][d] |= f[i-1][j-1][tk][d];
}
else{
int tk = k + (d ? 1 : -1);
if(tk >= 0 && tk <= (m<<1))
f[i][j][k][d] |= f[i-1][j][tk][d];
if(j) f[i][j][k][d] |= f[i-1][j-1][k][!d];
}
}
int ans = 0;
for(int j = n; j >= 0; j -= 2)
for(int k = (m<<1); k >= 0; k--)
if(f[m][j][k][0] || f[m][j][k][1]){
ans = max(ans, abs(k - m));
}
printf("%d\n", ans);
}
int main(){
init();
work();
}