动态规划部分
这一周主要还是做了动态规划的题,他实在是难啃的的骨头,而且我之前没有关注到重点,导致我每次做题都很困难,没有想法没有思路,然后就只能想到最朴素最朴素的方法,然后就只能去看别人写的。但是!现在!我知道了,重点是得出转移方程来,然后转移方程就是根据题目条件得来的,要求是啥就让dp[i][j]中的i和j换成啥,主要是循环,根据下标做循环,把所有子问题的解先求出来
再就是根据问题写方程,转换方程无非就是取最值,加加减减之类的,具体问题具体分析。
当你没有思路的时候,就在纸上模拟,重点是画图,然后找规律,横纵坐标就是题目的要求和条件。
用两个题来表达我做题的大致思想
第一个题写详细点
1.Worm
每过1分钟,毛毛虫会随机从一棵树爬到相邻的一棵树上。现在告诉你苹果树的数目N,以及毛毛刚开始所在的位置P,请问,在M分钟后,毛毛虫到达第T棵树,一共有多少种行走方案数。
所以我们要找的条件就是时间和位置,显然两个条件就需要一个二维数组。
用i表示时间,j表示当前时间所在的位置,所以d[i][j]就是在i分钟时,虫子走到这一位置的方案数。
接下来是转移方程,因为在这一位置的上一步,虫子可能是从上一分钟的右边或者是左边来的,所以方案的可能数要把这两种情况都加上。
转移方程: dp[i][j]+=dp[i-1][j-1]+dp[i-1][j+1];
求所有符合情况的个数
这种类型的题就是有的值是一定的,他本身有自己固定的个数,只需要判断出符合哪一种即可,所以是提前写一个函数,把所有情况都包括。
2.Mashmokh ACM
如果一个数列中,后一个数都能被前面一个数整除,那么就叫这个数列为好数列。
输入n,k,求数列中最大元素为n,数列长度为k的好数列的总个数
确定状态转移方程的两个元素,一个是最大元素(i),一个是数列的长度(j),所以用二维数组来转移。一个数可以被它后面的数整除,所以需要一个新的循环来判断可以整除它的又有哪些。
d[i][j]表示的是以j结尾的以i为长度的个数。
那我们的状态转移方程就可以写成
dp[i+1][k]=dp[i+1][k]+dp[i][j]
cf刷题部分
1.先说今天做了一个跟麻将有关的题,在终于理解题意之后的第一想法就是把所有需要的条件都写出来,符合谁的谁就赢。
但是最后没有成功,是因为一些题目的小细节处理错误了,越是长的代码越容易犯细节性的小错误,所以要在纸上提前清楚的写出来。
去看了别人的代码,用了map,代码是缩短了一些,但是以我现在的水平,我喜欢更直接的办法。
在这个题里面map的简便之处在于,对题目中的每种字符串的个数的记录很方便,不然要自己一个一个打出来去判断,个数多的话map就很有用了
map<string,int>mp;//记录这个字符串出现的次数
2.给一个位数小于100的一个整数,删掉其中的一部分或者不删除数字,然剩下的数字可以被8整除。显然100位太长了,不能直接循环。
由于1000可以被8整除,所以任何大于1000的数值可以分解为1000*a+b的形式,所以我们只需要看b,所以我们只需要在数字中找1位,2位,3位的数字观察其能否被8整除即可。
由这个套路可以去寻找其他数字的规律,进而判断。
博弈部分
巴什博弈,尼姆博奕等等之类的取石子的游戏都有一个固定的模板,思想和公式都是一样的,他只是会在原型的基础上增加一些条件而已。
这个周做到了威佐夫博弈的题
原型:
有两堆若干物品,两人轮流从其中一堆取至少一件物品,至多不限,或从两堆中同时取相同件物品,规定最后取完者胜利。威佐夫博弈就是,先拿者必败态叫做奇异局势。(例:(0,0)、(1,2)、(3,5)、(4,7)、……
判断点(a,b)是否是奇异局势,公式:c=floor((b-a)*(1+√5)/2])
如果c==小值,则必败,否则必胜。
变式:
增加要求,如果你胜,输出使你胜的你第1次取石子后剩下的两堆石子的数量x,y,x<=y。他一种情况是在任意的一堆中取走石子能胜,另一种是在两堆中同时取走相同数量的石子能胜,先手胜就是非奇异局势,先手想要胜利,就是不断把非奇异局势变成奇异局势
整体心得
有太多的东西需要去学,需要去熟练了,通过最近晚上练的题来看,好像目前还是只会做一些简单的题。对于题目稍微长和稍微难些的,对题意的理解就会有误差,调试代码的过程就会加长,并且出错的概率就会很大,每次都会被罚时罚到倒一,所以提交要慎重,读题要仔细。
不过长进也是有的,就是在看完题后就会大致判断了这个题是什么类型(仅限于我了解的),然后去决断它可不可以做。也就进步了这么一丝丝吧。