垒骰子

垒骰子


赌圣atm晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体。
经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥!
我们先来规范一下骰子:1 的对面是 4,2 的对面是 5,3 的对面是 6。
假设有 m 组互斥现象,每组中的那两个数字的面紧贴在一起,骰子就不能稳定的垒起来。 atm想计算一下有多少种不同的可能的垒骰子方式。
两种垒骰子方式相同,当且仅当这两种方式中对应高度的骰子的对应数字的朝向都相同。
由于方案数可能过多,请输出模 10^9 + 7 的结果。


不要小看了 atm 的骰子数量哦~


「输入格式」
第一行两个整数 n m
n表示骰子数目
接下来 m 行,每行两个整数 a b ,表示 a 和 b 不能紧贴在一起。


「输出格式」
一行一个数,表示答案模 10^9 + 7 的结果。


「样例输入」
2 1
1 2


「样例输出」
544


「数据范围」
对于 30% 的数据:n <= 5
对于 60% 的数据:n <= 100
对于 100% 的数据:0 < n <= 10^9, m <= 36




资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 2000ms




请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。


所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。

注意:主类的名字必须是:Main,否则按无效代码处理。



这个是之前有人问的一个问题,  我没有对应的验证网页,所以我这里就只分享我的思路   对于具体的限制可能需要调整下代码



首先题目中的隐含的条件是骰子的的6个数是有位置限制的,也就是我们确定了相邻两面就能确定整个骰子的方位,

根据上面一条我们就能知道,在确定一层的骰子的时候 确定了底面的时候 这个骰子只可能有4种情况,这个条件可以被我们用来优化中间处理过程,也就是这个题目可以转化成确定每层骰子的底层数字序列,最后结果需要乘以4^n ,n代表着层数

另外对于给出的不相容序列的限制,我们可以理解成每层骰子底面数字构成 的序列存在着相邻数必须满足的一个不相容的条件,比如1 2不相容,相邻两个数不能是4,2   或者是5,1   


综上我们可以得出平凡的解题思路,读入层数与不相容条件个数  ->读入不相容条件,将它转化成不相容的相邻数字对,最后把它纳入map中存储(因为存在着1个数字与多个数字不相容的情况,并且可以提高查找效率)->使用回溯法确认地面数字序列个数(因为如果从头部开始考虑,一个数字的选取会影响到下一个数字的选择)->将序列个数乘以4^n  然后输出


注意点

1中间数字可能溢出,需要处理掉,题目中给出了mod 的方法,但是我们不能用先乘后比较的方法,这样已经溢出的情况可能发现不了,我们需要先把mod的数除以乘数来比较,这样要防守的方法避免数据的溢出


2使用回溯法的时候需要保存中间数据,因为数据量会很大,比如我们确定序列第二位取2的情况下可能有100种,那么我们下次遇到第二位需要取2的情况时 我们只需要读一遍数据就好了,    也就是我们可能需要开一个 6*10^9 的数组,  当然如果为了空间考虑 我们可以只开一部分,也就是比如我们缓存 第6位取个各种值的情况,第5位 。。。。第2位,这样我们一共需要cache 30个数,  这样也能满足大多数情况的需求,  具体编程环境  具体选择吧



以上

你可能感兴趣的:(数据结构与算法)