OpenJudge-2663:完美覆盖

描述
一张普通的国际象棋棋盘,它被分成 8 乘 8 (8 行 8 列) 的 64 个方格。设有形状一样的多米诺牌,每张牌恰好覆盖棋盘上相邻的两个方格,即一张多米诺牌是一张 1 行 2 列或者 2 行 1 列的牌。那么,是否能够把 32 张多米诺牌摆放到棋盘上,使得任何两张多米诺牌均不重叠,每张多米诺牌覆盖两个方格,并且棋盘上所有的方格都被覆盖住?我们把这样一种排列称为棋盘被多米诺牌完美覆盖。这是一个简单的排列问题,同学们能够很快构造出许多不同的完美覆盖。但是,计算不同的完美覆盖的总数就不是一件容易的事情了。不过,同学们 发挥自己的聪明才智,还是有可能做到的。
现在我们通过计算机编程对 3 乘 n 棋盘的不同的完美覆盖的总数进行计算。



任务
对 3 乘 n 棋盘的不同的完美覆盖的总数进行计算。
输入
一次输入可能包含多行,每一行分别给出不同的 n 值 ( 即 3 乘 n 棋盘的列数 )。当输入 -1 的时候结束。

n 的值最大不超过 30.
输出
针对每一行的 n 值,输出 3 乘 n 棋盘的不同的完美覆盖的总数。

吐槽:还想了很久。。。果然数学思维弱~~o(>_<)o ~~

思路:

其实很容易通过给出的图来发现中间(也就是第三列-第六列)的那种铺法是要另外算的。

然后又很容易得出dp[i]=dp[i-2]*3; (奇数不行,然后如果新加进去的两列,也就是面积为2*2的方格加到最后的话,那么肯定方案数是乘3的)

那么我们刚刚说的那种方案要怎么求呢?其实我们上面的求的是当那个奇怪形状的东西在左边的时候然后右边随便加的情况,那么我们还要让奇怪的形状在右边,然后左边随便加的情况。因为那个形状放左边和右边是两种不一样的情况(因为那个形状只有上面全部横着放和下面全部横着放两种)。所以dp[i]+=2*(dp[i-4]+dp[i-6]+...+dp[0]);


#include
#include
#include
#include
#include
#include
using namespace std;
#define maxn 33
typedef long long ll;
ll dp[maxn];
int main(){
    int n;
    dp[0]=1; dp[2]=3; dp[4]=11;
    for(int i=6;i<=30;i+=2){
        dp[i]=dp[i-2]*3;
        int t=i-4;
        while(t>=0){
            dp[i]+=dp[t]*2;
            t=t-2;
        }
    }
    while(~scanf("%d",&n)){
        if(n==-1) break;
        printf("%lld\n",n%2==0?dp[n]:0);
    }
    return 0;
}

你可能感兴趣的:(数学题)