Newcoder 70 E.乌龟跑步(dp)

186 篇文章 0 订阅

Description

有一只乌龟,初始在 0 0 0的位置向右跑。

这只乌龟会依次接到一串指令,指令 T T T表示向后转,指令 F F F表示向前移动一个单位。乌龟不能忽视任何指令。

现在我们要修改其中正好 n n n个指令(一个指令可以被改多次,一次修改定义为把某一个 T T T变成 F F F或把某一个 F F F变成 T T T)。

求这只乌龟在结束的时候离起点的最远距离。(假设乌龟最后的位置为 x x x,我们想要 ∣ x ∣ |x| x最大,输出最大的 ∣ x ∣ |x| x

Input

第一行一个字符串 c c c表示指令串。 c c c只由 F F F T T T构成。

第二行一个整数 n n n

( 1 ≤ ∣ c ∣ ≤ 100 , 1 ≤ n ≤ 50 ) (1\le |c|\le 100, 1\le n\le 50) (1c100,1n50)

Output

一个数字表示答案。

Sample Input

FT
1

Sample Output

2

Solution

d p [ i ] [ j ] [ k ] [ l ] dp[i][j][k][l] dp[i][j][k][l]表示前 i i i步走到 j j j位置( j ∈ [ − m , m ] j\in[-m,m] j[m,m],其中 m = ∣ c ∣ m=|c| m=c),修改了 k k k次且当前方向为正/反方向 ( l = 0 / 1 ) (l=0/1) (l=0/1)的这种方案是否存在,若存在,则第 i + 1 i+1 i+1步有两种选择,要么不修改要么修改一次,进而有
d p [ i + 1 ] [ j + l ? − 1 : 1 ] [ k ] [ l ] = 1 , c i + 1 = F d p [ i + 1 ] [ j ] [ k ] [ 1 − l ] = 1 , c i + 1 = T d p [ i + 1 ] [ j + l ? − 1 : 1 ] [ k ] [ l ] = 1 , c i + 1 = T , k &lt; n d p [ i + 1 ] [ j ] [ k ] [ 1 − l ] = 1 , c i + 1 = F , k &lt; n \begin{array}{lcl} dp[i+1][j+l?-1:1][k][l]=1,c_{i+1}=F\\ dp[i+1][j][k][1-l]=1,c_{i+1}=T\\ dp[i+1][j+l?-1:1][k][l]=1,c_{i+1}=T,k&lt;n\\ dp[i+1][j][k][1-l]=1,c_{i+1}=F,k&lt;n\\ \end{array} dp[i+1][j+l?1:1][k][l]=1,ci+1=Fdp[i+1][j][k][1l]=1,ci+1=Tdp[i+1][j+l?1:1][k][l]=1,ci+1=T,k<ndp[i+1][j][k][1l]=1,ci+1=F,k<n
最后找到使得 d p [ m ] [ j ] [ k ] [ l ] = 1 dp[m][j][k][l]=1 dp[m][j][k][l]=1 j , n j,n j,n奇偶性相同的 ∣ j ∣ |j| j最大值即为答案,时间复杂度 O ( m 2 n ) O(m^2n) O(m2n)

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=105;
char s[105];
int n,dp[105][205][55][2];
int main()
{
	scanf("%s%d",s,&n);
	int m=strlen(s);
	dp[0][m][0][0]=1;
	for(int i=0;i<m;i++)
		for(int j=-m;j<=m;j++)
			for(int k=0;k<=n;k++)
				for(int l=0;l<=1;l++)
					if(dp[i][j+m][k][l])
					{
						if(s[i]=='F')dp[i+1][j+(l?-1:1)+m][k][l]=1;
						else dp[i+1][j+m][k][l^1]=1;
						if(k<n)
						{
							if(s[i]=='F')dp[i+1][j+m][k+1][l^1]=1;
							else dp[i+1][j+(l?-1:1)+m][k+1][l]=1;
						}
					}
	int ans=0;
	for(int i=-m;i<=m;i++)
		for(int j=0;j<=n;j++)
			for(int k=0;k<=1;k++)
				if(dp[m][i+m][j][k]&&(n-j)%2==0)
					ans=max(ans,abs(i));
	printf("%d\n",ans);	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值