有一个海龟在一个x轴的0点,给出一个由'F','T'组成的字符序列。c++
海龟要按照这个序列进行行动,若是第i个字符为'F',表示沿当前方向走,'T'表示转身。spa
如今你必须改变n个操做,把'F'变成'T',或者把'T'变成'F',同一个操做能够改变屡次,问终点距离起点最大距离。code
看数据范围就是DP。get
先说正解。博客
dp[i][j][0]
表示执行完前i步,改变了j次,方向为正对起点的最大距离it
dp[i][j][1]
表示执行完前i步,改变了j次,方向为背对起点的最大距离class
对于每一个操做,枚举改变的次数num,而后分别讨论为F,T的状况数据
str[i]=='F'
:co
num%2==0 :改变偶数次至关于没改变,向前走了一步字符
dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-num][0]-1);
正对起点向前走,距离减少1
dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-num][0]+1);
与上相反
num%2==1:改变奇数次至关于改变一次,转身
dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-num][1]);
dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-num][0]);
str[i]=='T'
: 就和F中num的奇偶性相反
初始化dp[0][0][0]=dp[0][0][1]=0.
,其余为负无穷
这题我想了两个DP方程,上面是第二个。
第一个是dp[i][j][k][l]
表示前i个命令距离起点为j改变了k次朝向为l是否可行
GG了,写了很久混乱了
#include<bits/stdc++.h> #define pb push_back using namespace std; typedef long long ll; const int N=1e4+10; const int mod=1e9+7; const int inf=0x3f3f3f3f; int dp[110][110][55]; /* dp[i][j][k]前i条命令改变了j次,朝向为k的最远距离 */ char str[N]; int main() { scanf("%s",str+1); int len=strlen(str+1),k; scanf("%d",&k); memset(dp,0x8f,sizeof(dp)); dp[0][0][1]=0; dp[0][0][0]=0; for(int i=1; i<=len; i++) { for(int j=0; j<=k; j++) { for(int l=0; l<=j; l++) { if(str[i]=='F') { if(l%2) { dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-l][1]); dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-l][0]); } else { dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-l][1]+1); dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-l][0]-1); } } else { if(l%2==0) { dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-l][1]); dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-l][0]); } else { dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-l][1]+1); dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-l][0]-1); } } } } } printf("%d\n",max(dp[len][k][0],dp[len][k][1])); return 0; }