• 「CodePlus 2018 3 月赛」白金元首与莫斯科


    $n leq 17,m leq 17$,$n*m$的01矩形,对每一个0问:当他单独变成1之后,在其他0处放多米诺牌(不一定放满,可以不放)的方案数。膜$1e9+7$。

    直接$dp$是$n^42^n$,很难受。这种整体挖一块的东西可以用拼接法,就是用那一块前的$dp$值和那一块后的$dp$值计算答案。

    $f(i,j,k)$--从$(1,1)$到$(i,j)$,在$(i,j)$前面$m$个格子状态$k$的方案数,$g(i,j,k)$--从$(n,m)$到$(i,j)$,在$(i,j)$后面$m$个格子状态$k$的方案数。状态$k$中1表示这一位是障碍或放了牌,0表示还没放。

    然后来看$f(i,j,k)$和$g(i,j,k)$怎么合并出$(i,j)$的答案。画画图可以发现,$f(i,j,p)$和$g(i,j,q)$可以合并,除非他们空出的地方刚好对齐可以放竖的多米诺,表现为:$p,q$的第一位都是1,然后$p$和$q$的后$m-1$位恰好相反。因此可以$O(2^m)$算出一个点的答案。总复杂度$n^22^n$。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 //#include<math.h>
     5 //#include<queue>
     6 //#include<vector>
     7 #include<algorithm>
     8 //#include<iostream>
     9 //#include<assert.h>
    10 using namespace std;
    11 
    12 int n,m;
    13 const int mod=1e9+7;
    14 int g[18][18][132222],f[2][132222],cur;
    15 bool mp[18][18];
    16 
    17 int rev(int x) {int ans=x&1; for (int i=1;i<m;i++) ans|=((x>>i)&1)<<(m-i); return ans;}
    18 
    19 int main()
    20 {
    21     scanf("%d%d",&n,&m);
    22     for (int i=1;i<=n;i++) for (int j=1,x;j<=m;j++) scanf("%d",&x),mp[i][j]=x;
    23     
    24     g[n][m][(1<<m)-1]=1;
    25     for (int i=n;i;i--)
    26         for (int j=m;j;j--)
    27         {
    28             int ni=i,nj=j-1; if (nj==0) ni=i-1,nj=m; if (ni==0) break;
    29             for (int k=0,nk;k<(1<<m);k++) if (g[i][j][k])
    30             {
    31                 if ((k&1)==0 && i<n && !mp[i+1][j])
    32                 {if (!mp[i][j]) {nk=(k>>1)|(1<<(m-1)); g[ni][nj][nk]+=g[i][j][k],g[ni][nj][nk]-=g[ni][nj][nk]>=mod?mod:0;}}
    33                 else
    34                 {
    35                     nk=(k>>1)|(1<<(m-1)); g[ni][nj][nk]+=g[i][j][k],g[ni][nj][nk]-=g[ni][nj][nk]>=mod?mod:0;
    36                     if (!mp[i][j])
    37                     {
    38                         nk=(k>>1); g[ni][nj][nk]+=g[i][j][k],g[ni][nj][nk]-=g[ni][nj][nk]>=mod?mod:0;
    39                         if (j<m && ((k>>(m-1))&1)==0 && !mp[i][j+1])
    40                         {nk=(k>>1)|(1<<(m-2))|(1<<(m-1)); g[ni][nj][nk]+=g[i][j][k],g[ni][nj][nk]-=g[ni][nj][nk]>=mod?mod:0;}
    41                     }
    42                 }
    43             }
    44         }
    45     
    46     cur=0; f[0][(1<<m)-1]=1;
    47     for (int i=1;i<=n;i++,puts(""))
    48         for (int j=1;j<=m;j++)
    49         {
    50             int ans=0;
    51             if (!mp[i][j])
    52             for (int k=1;k<(1<<m);k+=2) ans+=1ll*f[cur][k]*g[i][j][rev(k)]%mod,ans-=ans>=mod?mod:0;
    53             printf("%d ",ans);
    54             int ni=i,nj=j+1; if (nj>m) ni++,nj=1; if (ni>n) break;
    55             for (int k=0,nk;k<(1<<m);k++) if (f[cur][k])
    56             {
    57                 if ((k&1)==0 && i>1 && !mp[i-1][j])
    58                 {if (!mp[i][j]) {nk=(k>>1)|(1<<(m-1)); f[cur^1][nk]+=f[cur][k],f[cur^1][nk]-=f[cur^1][nk]>=mod?mod:0;}}
    59                 else
    60                 {
    61                     nk=(k>>1)|(1<<(m-1)); f[cur^1][nk]+=f[cur][k],f[cur^1][nk]-=f[cur^1][nk]>=mod?mod:0;
    62                     if (!mp[i][j])
    63                     {
    64                         nk=(k>>1); f[cur^1][nk]+=f[cur][k],f[cur^1][nk]-=f[cur^1][nk]>=mod?mod:0;
    65                         if (j>1 && ((k>>(m-1))&1)==0 && !mp[i][j-1])
    66                         {nk=(k>>1)|(1<<(m-1))|(1<<(m-2)); f[cur^1][nk]+=f[cur][k],f[cur^1][nk]-=f[cur^1][nk]>=mod?mod:0;}
    67                     }
    68                 }
    69                 f[cur][k]=0;
    70             }
    71             cur^=1;
    72         }
    73     return 0;
    74 }
    View Code

    话说这代码调了好久的。。是个小错误,以后调代码得静下心了。

  • 相关阅读:
    文本挖掘预处理之TF-IDF
    文本挖掘预处理之向量化与Hash Trick
    文本挖掘的分词原理
    MCMC(四)Gibbs采样
    MCMC(三)MCMC采样和M-H采样
    编译c时提示“dereferencing type-punned pointer will break strict-aliasing rules”如何处理?
    ubuntu下添加新的ppa软件源后出现"Error: retrieving gpg key timed out"如何处理?
    如何创建离线网页?
    ubuntu下如何安装wpantund?
    tmux如何调节窗口大小?
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8820362.html
Copyright © 2020-2023  润新知