[Seoul 2007]Tile走道铺砖翻转问题处理

总时间限制: 

20000ms

单个测试点时间限制: 

1000ms

内存限制: 

131072kB

描述

还是传统的走道铺砖问题,还是2行N列,现在给你三种砖,其规格分别为1*2,2*1,2*2。现在用这三种砖将走道铺满且砖与砖块之间不能重叠。问有多少种做法,值得注意的是:如果一种铺放的方法可以由另一个翻转过来得到则这两种只视为一种放法

输入

现给出N的值,请问有多少种不同的放法

输出

如题

样例输入

Sample input 1
2

Sample input 2
4

样例输出

Sample output 1
3
Sample output 2
8

提示

100%的数据,N<=10000

这道题目最大的难点在于,题目中说的:“如果一种方法是通过另一种方法翻转得到的则两种方法视为一种”,这也就是说咱们通过动规得到铺砖方法总数后还得排除掉通过翻转得到的那部分铺砖方法;
1.首先不考虑翻转我们知道dp[n]=dp[n-1]+2*dp[n-2], dp[n] 代表2行n列时的铺砖方法数,这部分就不细说了,关于动态归化的内容网上随便一搜就一堆的解释了,到这一步我们就已经算出不考虑翻转问题时的总铺砖数量为dp[n]
伪代码:
int dp[1]=1; int dp[2]=3;
for(int i=3;i<=n;i++){
dp[i]=dp[i-1]+2*dp[i-2];
}

2.算出不考虑翻转问题的铺砖方法数之后,再来考虑翻转部分,先一张图解释下什么是翻转 如下图2行3列的两种铺砖方法就是其各自翻转后的样子:


这样一来你就应该想到任何一种铺法都能这样翻转一下对吧,那总铺砖方法数dp[n]/2就把重复的过滤掉了吗???
但是代码写出来后还是提交不过,为啥???仔细一想发现有种特殊情况被忽略了,就是沿中心轴对称的情况,如下2行3列的其中一种铺砖方法:

类似这种铺法不存在对应翻转之后的铺法的,因为它翻转之后还是它本身,那么我们假设沿中轴线对称的铺法数量为c[n],
所以最后实际铺砖方法数量为(dp[n]-c[n])/2+c[n]
3.那c[n]怎么得到?我们可以这样想,既然是对称的那中轴线左右两边的铺法肯定要是一样的,那c[n]=dp[n/2]吗???不完全对,
这里我们需要看n是奇数还是偶数,奇数时中轴线上必定是一个2X1的砖块c[n]=dp[n/2] (n/2取整)没问题,偶数时中轴线上可以是两个1X2或者1个2X2的砖块,或者中轴线上没有砖块.
如下图分别是中轴线上是两个1X2 1个2X2的砖块 无砖块

n=偶数时


可见中轴线上有砖块时,有两种情况2dp[n/2-1]+,中轴线上无砖块时dp[n/2]
所以**n为偶数时c[n]=2
dp[n/2-1]+dp[n/2]*
所以最终结果:
if(n%2==0){
result = (dp[n]-2
dp[n/2-1]+dp[n/2])/2+2*dp[n/2-1]+dp[n/2];
}else{
result =(dp[n]-dp[n/2])/2+dp[n/2];
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔刀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值