hdu2606 Renovation Problem(递推)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2606

题意:有四种砖规格分别是 1*1 2*2 3*3 4*4,现在已知一个4*n的矩形,问刚好铺满这个矩形有多少种方案?

解题:题目说的是4*n的矩形,我把矩形倒过来看,也就是一个n*4的矩形,也就是只有四列的矩形

dp[i] 表示铺满前i行的方案数,对于第i行的4个方块,它只可能这几种情况中一种:1111  2211 1122 1221 2222 3331 1333 4444

对于1111 的摆放,得到  dp[i]  += dp[i-1]; 也就是最后一行我确定了,然后前面的i-1行随便你放,下面类似。

对于3331 1333的摆放,得到dp[i] += dp[i-3]*2;

对于4444的摆放,得到 dp[i] += dp[i-4];  

然而 对于2211 1122 1221 2222 的摆放,这就有点麻烦了,你可能会问为什么不能直接 dp[i] += dp[i-2] * 4

如果单纯加上dp[i-2]*4 就会缺失了一些特殊情况,比如3*4的矩阵,dp[i-2]*4 代表的情况如下:

1111    1111     1111      1111

2211    1221    1122     2222 

扫描二维码关注公众号,回复: 2511996 查看本文章

2211    1221    1122     2222

但缺少了这两种特殊情况

2211             1122

2222             2222

1122             2211

我们可以知道只有2*2这种砖块,才会存在这种问题。因为 22xx,剩下的两格xx可以是22 或者11,如果是333x,x就只能是1。

这部分特殊怎么推,语言很难描述,也怕讲错了,不过只需要画出4*4的情况,自己揣摩一下就可以了,这部分特殊情况的解是 top[i-3]*2  (top[n] = dp[0] + dp[1] + .. + dp[n])。

边界:dp[0]=dp[1] =1   dp[2] = 5

#include<stdio.h>
typedef long long ll;
ll dp[100+10]={1,1,5,13};// dp[i]表示铺满前 i 行的方案数
ll top[100+10]={1,2,7,20};// top[n] = dp[0] + dp[1] + dp[2] +...+dp[n]
const ll mod = 19890907;
void init()
{
    for(int i=4;i<=100;i++)
    {
        dp[i] = dp[i-1]%mod;
        
        dp[i] = (dp[i] + dp[i-2]*4%mod)%mod;
        dp[i] = (dp[i] + top[i-3]*2%mod) %mod;
        
        dp[i] = (dp[i] + dp[i-3]*2%mod)%mod;
        
        dp[i] = (dp[i] + dp[i-4])%mod;
        
        top[i] = (top[i-1] + dp[i]) %mod;
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    init();
    while(t--)
    {
        int n;
        scanf("%d",&n);
        printf("%lld\n",dp[n]%mod);
    }
    return 0;
}//15ms  c++

加油吧,渣科

猜你喜欢

转载自blog.csdn.net/zark721/article/details/81159744