zoukankan      html  css  js  c++  java
  • 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]);
    }
  • 相关阅读:
    USART串口通信实验
    EXTI 外部中断
    NVIC中断优先级管理
    实验1 跑马灯实验
    redis集群部署---一台主机
    zookeeper服务启动报错---Error contacting service. It is probably not running.
    shell脚本学习笔记
    最短路径算法——Floyd算法
    一篇文章学懂Shell脚本(摘抄)
    VIM空格和TAB转换
  • 原文地址:https://www.cnblogs.com/dancer16/p/7338548.html
Copyright © 2011-2022 走看看