给一个含有T、F的字符串,T表示转向,F表示前进1格。现在可以把其中的T改为F,或F改为T,改变n次(可重复改变某一位置的字母),问相对于起点最远能走多远。
考虑每一个命令,选择改变或者不改变,当前的决策对于以后产生的影响就是,停在了哪个位置,正朝着哪个方向。
由此可以设出状态:dp[i][j][k][d]表示前i个命令,使用了j次机会,当前停留在k位置,正朝着d方向。
不妨设初始位置为L,则最右可到达2×L,最左可达到0位置
不妨设初始位置为L,则最右可到达2×L,最左可达到0位置
#include<bits/stdc++.h>
using namespace std;
bool dp[101][51][201][2];
char s[105];
int main()
{
int i,j,k,d,n,L;
scanf("%s%d",s+1,&n);
L=strlen(s+1);
dp[0][0][L][1]=1;
for(i=1;i<=L;++i)
for(j=0;j<=n;++j)
for(k=0;k<=2*L;++k)
for(d=0;d<2;++d)
{
if(!dp[i-1][j][k][d]) continue;
int d1=d,d2=d,K;
if(s[i]=='T')
{
d1=!d;
K=k;
}
else
{
if(d) K=k+1;
else K=k-1;
}
dp[i][j][K][d1]=1;
if(j<n)
{
if(s[i]=='F')
{
d2=!d;
K=k;
}
else
{
if(d2) K=k+1;
else K=k-1;
}
dp[i][j+1][K][d2]=1;
}
}
int ans=0;
for(i=n;i>=0;i-=2)
for(j=0;j<=2*L;++j)
for(d=0;d<2;++d)
if(dp[L][i][j][d]) ans=max(ans,abs(j-L));
printf("%d\n",ans);
return 0;
}