51nod1033

骨牌覆盖,一开始写了插头DP。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring> 
#define pp 1000000007
using namespace std;
long long dp[3][6][65];
int n,m;
int main()
{
    scanf("%d %d",&n,&m);
    dp[0][m][0]=1;
    for(int i=1;i<=n;i++)
    {
        memset(dp[1],0,sizeof(dp[1]));
        for(int sta=0;sta<(1<<m);sta++)
        {
            dp[1][0][sta<<1]=dp[0][m][sta];
        }
        for(int j=1;j<=m;j++)
            for(int sta=0;sta<(1<<(m+1));sta++)
            {
                int x=1<<(j-1);
                int y=1<<j;
                if((sta&x)==0&&(sta&y)==0)
                dp[1][j][sta]=(dp[1][j-1][sta+x]+dp[1][j-1][sta+y])%pp;
                if((sta&x)==0&&(sta&y)!=0)
                dp[1][j][sta]=dp[1][j-1][sta-y];
                if((sta&x)!=0&&(sta&y)==0)
                dp[1][j][sta]=dp[1][j-1][sta-x];
                //cout<<i<<' '<<j<<' '<<sta<<' '<<dp[i][j][sta]<<endl;
            }
        for(int j=1;j<=m;j++)    
            for(int sta=0;sta<(1<<(m+1));sta++)
            {
                dp[0][j][sta]=dp[1][j][sta];
            }        
    }
    cout<<dp[1][m][0]<<endl;
 } 

果断T掉,后来知道动态规划的原理就是把状态看成点,转移看成边,就是一个拓扑图。而这道题它的拓扑图结构比较清晰,要求的方案数可以用矩阵乘法来做,但是插头DP的状态与行列的值有关,好像不能这么搞。要用状压系列的(晕~~)。

代码转自http://blog.csdn.net/naipp/article/details/52815127

#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
typedef long long LL;
typedef unsigned long long ULL;


typedef vector<LL> vec;
typedef vector<vec> mat;

// A*B
mat mul(mat& A, mat& B)
{
    mat C(A.size(), vec(B[0].size()));
    for(int i = 0; i < (int)A.size(); ++i)
        for(int j = 0; j < (int)B[0].size(); ++j)
            for(int k = 0; k < (int)B.size(); ++k)
                C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
    return C;
}

// A^n
mat pow(mat A, int n)
{
    mat B(A.size(), vec(A.size()));
    for(int i = 0; i < (int)A.size(); ++i) B[i][i] = 1;
    while(n)
    {
        if(n & 1) B = mul(B, A);
        A = mul(A, A);
        n >>= 1;
    }
    return B;
}
int n,m;
LL dp[1<<5][1<<5];
void dfs(int c,int pre,int now){
    if(c>n)return ;
    if(c==n){
        dp[pre][now]++;
        return ;
    }
    dfs(c+1,pre<<1,now<<1|1);
    dfs(c+1,pre<<1|1,now<<1);
    dfs(c+2,pre<<2,now<<2);
}


int main()
{
        cin>>m>>n;
        mat a(1<<n,vec(1<<n));
        dfs(0,0,0);
        for(int i=0;i<(1<<n);i++){
            for(int j=0;j<(1<<n);j++){
                a[i][j]=dp[i][j];
                //cout<<a[i][j];
            }
            //cout<<endl;
        }
        a=pow(a,m+1);
        printf("%lld
",a[0][(1<<n)-1]);
}
原文地址:https://www.cnblogs.com/dancer16/p/7338548.html