最近浏览到CCF的题,刚开始做,做了前两道都没问题通过,第三道内存超限,90分。第四道,时间超时,10分。让我很郁闷。因此在网上百度了一下下。大部分的解决方案都是使用了动态规划的思想。大三学生,刚学了算法。编程中没有想到去使用它。说明我学的有多么烂了。目前的状态就是能看懂也能理解算法的思想,但是遇到问题想要去使用动态规划的时候,却没有思路。很郁闷。不知道该怎么解决这个问题。如果有大佬,还请不吝赐教。
步入正题,有趣的数。
给出题目:
试题名称: 有趣的数
时间限制: 1.0s
内存限制: 256.0MB
问题描述: 问题描述
我们把一个数称为有趣的,当且仅当:
1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次。
2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前。
3. 最高位数字不为0。
因此,符合我们定义的最小的有趣的数是2013。除此以外,4位的有趣的数还有两个:2031和2301。
请计算恰好有n位的有趣的数的个数。由于答案可能非常大,只需要输出答案除以1000000007的余数。
输入格式
输入只有一行,包括恰好一个正整数n (4 ≤ n ≤ 1000)。
输出格式
输出只有一行,包括恰好n 位的整数中有趣的数的个数除以1000000007的余数。
样例输入
4
样例输出
3
解题思路:
通过题目的规则。将其分为六个状态。很多人不知道六个状态是怎么想出来的。我也不知道,如果我能想出来也不必这么纠结了。但是搞明白了原因。在下面的分析中,我会忽略某些简单的问题,因为自己去思考效果更好。
状态1:首先,第一位只能为2。所以只使用了2的状态成为状态1
状态2:状态2和状态3可以一起考虑。第一位为2,或者说前面不管多少位只使用了2(013没有用到),那后续的数字可以为0或者3,状态2暂且定义为使用过2和0(13没有用到)
状态3:暂且定义为使用过2和3(01没有用到)
状态4:使用其中两个的结束之后应该是使用其中三个。使用过2和0之后,可以在使用1或者3都可以。使用过2和3之后只能使用0.因为0必须在1之前。这样又分化出两个状态。状态4定义为使用了2和0和3(1没有用到)
状态5:定义为使用了2和0和1(3没有用到)
状态6:三个数字全部用过之后,就是四个数字了。也就是0,1,2,3全部用到。定义为状态6.
6个状态分析结束了。可以发现有两个变量。一个是输入的位数。一个是四个数字分别出现的个数。
输入的位数不需要再说了。来看看这个个数怎么处理。
定义一个二维数组。横坐标表示输入的位数。纵坐标表示6个状态。
这样二维数组中右下角的数字就是满足题目要求的数字的个数。
在使用动态思想:最优解解是前n-1步的最优解+第n步的最优解
状态1(2)情况: 前n-1位只使用2(也就是状态1),第n位也只能使用2(为了满足状态1)
状态2(2,0)情况:前n-1位只使用2(也就是状态1),第n位使用0(变成状态2)或者前n-1位使用2 0(也就是原本就是状态2),第n位使用0或2 (仍然保证它是状态2)
状态3(2,3)情况:前n-1位只使用2(也就是状态1),第n位使用3(变成状态3)或者前n-1位使用2 3(也就是原本就是状态3),第n位使用3 (因为已经有了3了不能用2了,满足规则只能用3让它仍然保证是状态3)
状态4(2,0,3)情况: 前n-1位使用2 0(也就是状态2),第n位使用3(变成状态4)或者前n-1位使用2 3(也就是状态3),第n位使用0(变成状态4)或者前n-1位使用2 0 3(也就是原本就是状态4),第n位使用0或3 (因为已经有了3了不能用2了,满足规则只能用3让它仍然保证是状态4)(为了保证状态4,所以子状态不可能是状态1)
状态5(2,0,1)情况:前n-1位使用2 0(也就是状态2),第n位使用1(不使用3是为了让它满足状态5)或者 前n-1位使用2 0 1(也就是原本就是状态5),第n位使用1或2 (因为已经有了1了不能用0了,满足规则只能用1让它仍然保证是状态5)(为了保证状态5,所以子状态不可能是状态1或者状态3或者状态4)
状态6(2,0,1,3)情况: 前n-1位使用2 0 1(也就是状态5),第n位使用3(变成状态6)或者前n-1位使用2 0 3(也就是状态4),第n位使用1(变成状态6)或者前n-1位使用2 3 0 1(也就是原本就是状态6),第n位使用1或3(因为已经有了1,3了不能用0,2了,满足规则只能用1,3让它仍然保证是状态6)
不明白的可以留言。代码就不放了,百度一堆。此文仅帮助不能理解这6个状态的学者。