◆考试题目◆◇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; }
相关文章推荐
- ◆考试题目◆◇NOIP模拟赛◇robot(机器人)
- 2003年11月系分考试上午试题的一道题目
- 数据库考试题目
- java考试题目◎.◎b(转)
- QTP sp等级历年的一些考试辅导题目!(分享)
- 2007浙大复试上机考试题目1--最小长方形
- C语言考试2 题目整理
- Android如何强制刷新view--比较偏的考试题目
- 考试题目“笨笨玩游戏”
- 计算机等级考试二级C语言超级经典400道题目
- 一道有趣的C#考试题目
- 2012届华为校园招聘上机考试题目1(9月6日下午1点场)
- 10 25日考试 数学题目练习 斐波拉契 打表
- PAT考试乙级1045(C语言实现)重点题目(思路)
- CCIE的考试题目与分析--转自我的一位同事
- 全面分析RHCE7(红帽认证工程师)考试题目之 ----Samba文件共享篇
- C考试题目
- 部门培训阶段考试题目,你会几道?
- 考试题目<一>
- 2012 届华为校园招聘上机考试题目(9 月 6 日下午 1 点场)