有一個海龜在一個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; }