题解 CF132C 【Logo Turtle】
Sakurajima_Mai · · 题解
-
可以用三维
dp 来保存状态,dp[i][j][k] 表示在前i 个字符变换了j步之后方向为k(k = 1 or k = 0) 的最优解,也就是离原点的最大距离。这里规定0方向为正方向,1位负方向,表示的是当前这个人朝哪个方向。这两个方向是对立的。 -
所以就可以递推一个关系式,分第
i 个字符为F orT 时
1. 如果为F
- 依次枚举在第
i 个位置变换了几步,这是枚举的范围为[0,j] , 假设变换了k 步(和上面的dp[i][j][k] 当中的k 不是一个)
-
如果当
k 为奇数的时候,就是相当于变化了1步,所以F 就变成T 了,那么他的方向也因此变化了。所以当前的方向一定和上一步(也就是i - 1 时的方向)的方向相反,所以有dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][1]) ,同理,
dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][0]) -
如果
k 为偶数,相当于没有变化,所以还是字符F ,如果是正方向,那么他就可以由上一步继续向正方向走一步,也就是加1, 如果是负方向,相当于往回走一步,距离就减1,递推方程为:
dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][0] + 1); dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][1] - 1);
2.如果为T
依次枚举在第
-
如果
k 为奇数,这时就变化成了F ,所以dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][0] + 1); dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][1] - 1) -
如果
k 为偶数,这时还是T ,所以dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][1]); dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][0])
其中还有一个问题:
就是和刚开始的方向的无关,不用管朝哪个方向,只要走的最远的就行了,而且始终有两个相互对立的方向。初始化的时候
for (int i = 0; i <= len; i++)
for (int j = 0; j <= n; j++) dp[i][j][0] = dp[i][j][1] = -inf;
dp[0][0][0] = 0;//正方向
dp[0][0][1] = 0;//负方向,两边都可以走
for (int i = 1; i <= len; i++)
{
for (int j = 0; j <= n; j++)
{
for (int k = 0; k <= j; k++)
{
if (cmd[i] == 'F')
{
if (k & 1)
{
dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][1]);
dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][0]);
}
else
{
dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][0] + 1);
dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][1] - 1);
}
}
else
{
if (k & 1)
{
dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][0] + 1);
dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][1] - 1);
}
else
{
dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][1]);
dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][0]);
}
}
}
}
}