您的位置:首页 > 编程语言 > C语言/C++

◆考试题目◆◇NOIP模拟赛◇turtle(乌龟)

2017-11-02 13:33 337 查看

◇NOIP模拟赛◇turtle

Description

一只乌龟由于智商低下,它只会向左或向右走,不过它会遵循主人小h的指令:F(向前走一步),T(掉头)。现在小h给出一串指令,由于小h有高超的计算能力,他可以马上知道乌龟最后走到哪里。

为了难倒小h,他的好朋友小c就说,现在让你修改其中n个指令,使得乌龟移动到离起点最远的地方。(修改是指“T”变成“F”,或“F”变成“T”,可以对同一个指令多次修改)。乌龟一开始在0点。

Input

第1行:一个字符串S代表指令 (0<len≤100)

接下来一行一个整数n,表示要修改的指令个数 (0≤n≤50)

Output

第1行:一个整数,表示乌龟所能移动到的最远距离。

Sample Input

FFFTFFF
2


Sample Output

6


题目解析

这道题是一道有些变化的 资源分配DP 问题——将 j 次修改机会分配在前 i 个命令中。有变动的是阅读到某一命令时可以有向左或向右两种情况,于是在原来的状态数组 (g[i][j] ) 中增加一维,表示阅读到第i条指令时的方向(不妨设1向右,0向左)。

我们把乌龟爬的那一段直线抽象为一个数轴,它一开始在原点,最后它离原点的距离即它行走到的位置的绝对值(绝对值的几何意义),且由于一开始乌龟的方向并不影响最后的结果,我们不妨设乌龟一开始向右(正半轴)。这样就有一个问题——最后乌龟可以在数轴的正半轴,也可以在负半轴。那么我们就需要分别存阅读到第i条指令时的最小值和最大值——用 struct 存在一起。

那么数组就变成了这样:

struct Ans{int big,small;Ans() {big=-1e8,small=1e8;}}g[100][50][2];


注意定义时用构造函数分别给最大、最小值初始化。

接下来就是常规的 记忆化搜索 ,函数里的每一个参数都与数组 g 一一对应。注意它的返回值也是 Ans 。首先判断边界,当 len(当前阅读到的指令位置,从0开始)<0 ,也就是指令全部阅读完,就返回一个 “空” ,这里的空是一个 Ans 变量,那么我们就可以定义一个变量(Nothing)表示 “空” ,然后经过记忆化优化。

我们定义两个 Ans 变量(F1 , F2)分别表示不改变当前指令的值和改变当前指令的值。然后根据当前指令时 F 还是 T 分2类。由于必须把机会用完(由于一条指令可以改无数次,且当一条指令改偶数次时该指令是不变的,所以必须保证最后还剩余偶数次修改的机会),这里有一种情况是不能不修改的——当阅读到最后一条指令(len==0)时,剩余奇数次机会;同样有一种情况是必须不修改的——当阅读到最后一条指令时,剩余偶数次机会。排除这两种情况后,得出 F1 , F2 的值。g 的 big 和 small 就分别对应 F1 和 F2 中的 big 的较大值和 small 的较小值。

最后输出 g[len]
[1] 的 big 和 small 绝对值的最大值。

程序样例

(卡了一点数据,节省空间)

/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<cmath>
#define max(a,b) (a>b? a:b)
#define min(a,b) (a<b? a:b)
char code[100];
struct Ans
{
int big,small;
Ans() {big=-1e8,small=1e8;}
}g[100][50][2],Nothing;
bool vis[100][50][2];
Ans G(int len,int change,bool lr)
{
if(len<0) return Nothing;
if(vis[len][change][lr]) return g[len][change][lr];
vis[len][change][lr]=true;
int Flag=lr? 1:-1;
Ans F1,F2;
if(code[len]=='F')
{
if(len || change%2==0) F1=G(len-1,change,lr),F1.big+=Flag,F1.small+=Flag;
if((len || (!len && change%2)) && change) F2=G(len-1,change-1,!lr);
}
else
{
if(len || change%2==0) F1=G(len-1,change,!lr);
if((len || (!len && change%2)) && change) F2=G(len-1,change-1,lr),F2.big+=Flag,F2.small+=Flag;
}
g[len][change][lr].big=max(F1.big,F2.big);g[len][change][lr].small=min(F1.small,F2.small);
return g[len][change][lr];
}
int main()
{
Nothing.big=Nothing.small=0;
int change;
gets(code);scanf("%d",&change);
Ans ans=G(strlen(code)-1,change,1);
printf("%d",(int)max(fabs(ans.big),fabs(ans.small)));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息