zoukankan      html  css  js  c++  java
  • zoj 2563 Long Dominoes

    题目大意

      用1*3的骨牌覆盖一个n*m的矩阵,求方案数。

    分析

      m大小为9,状态压缩dp的标志,1*3的骨牌与上两层有关,故可以用2^18来表示状态,横放或者竖放,算一下时间复杂度 30*9*2^18=300000000,而题目只给了2s,晕,故这个题就是卡这种方法,于是就需要转换一下方法了,还是用状态压缩dp,不过这次改成3进制来表示

      0 表示横放或者竖放的第三个格子

      1 表示竖放的第一个格子

      2 表示竖放的第二个格子

      转移的有三个转移

      对应的上一行格子的数为

      0 表明这一行可以放横,也可以放竖的第一个格子

      1 表明这一行竖的第二个格子

      2 这一行只能放竖的第三个格子

    这样程序就不会超时了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<ctime>
    #include<cstring>
    #include<string>
    #include<set>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<algorithm>
    #include<sstream>
    #define inf 0x3f3f3f3f
    #define PI acos(-1.0)
    #define eps 1e-6
    #define LL long long
    #define MEM(a,b) memset(a,b,sizeof(a))
    #define PB push_back
    #define MK make_pair
    #define IN freopen("in.txt","r",stdin);
    #define OUT freopen("out.txt","w",stdout);
    #define BUG printf("bug************bug************bug
    ");
    
    using namespace std;
    LL dp[31][20000],P_3[20];
    LL n,m,row,state;
    int num[20];
    void init()
    {
         P_3[0]=1;
         for (int i=1;i<20;i++) P_3[i]=P_3[i-1]*3;
         //for (int i=1;i<20;i++) printf("%lld ",P_3[i]); printf("
    ");
    }
    void get_bit()
    {
         MEM(num,0);
         int k=0;
         LL ss=state;
         while(ss)
         {
              num[k++]=ss%3;
              ss/=3;
         }
    }
    void dfs(LL p,LL s)
    {
         if (p==m) {dp[row+1][s]+=dp[row][state]; return; }
         if (num[p]==0)
         {
              if (p+2<m && num[p+1]==0 && num[p+2]==0) dfs(p+3,s);
              dfs(p+1,s+P_3[p]);
         }
         if (num[p]==1) dfs(p+1,s+2*P_3[p]);
         if (num[p]==2) dfs(p+1,s);
    }
    int main()
    {
         init();
         while(scanf("%lld%lld",&m,&n)!=EOF && n+m)
         {
              if ((n*m)%3!=0) {printf("0
    "); continue; }
              LL maxn=P_3[m];
              MEM(dp,0);
              dp[0][0]=1;
              for (row=0;row<n;row++)
              {
                   for (state=0; state<maxn;state++)
                   {
                        if (dp[row][state])
                        {
                             get_bit();
                             dfs(0,0);
                        }
                   }
              }
              printf("%lld
    ",dp[n][0]);
         }
         return 0;
    }
  • 相关阅读:
    常见优化函数
    排序算法
    小米编程题
    leetcode 刷题
    beam_search 和 viterbi算法的区别
    快速排序
    vitrebi算法进行分词的案例
    python 进行视频剪辑
    keras实现MobileNet
    HMM、CTC、RNN-T训练时所有alignment的寻找方法
  • 原文地址:https://www.cnblogs.com/chensunrise/p/4198701.html
Copyright © 2011-2022 走看看