zoukankan      html  css  js  c++  java
  • 瓷砖铺放 (状压DP+矩阵快速幂)

    由于方块最多涉及3行,于是考虑将每两行状压起来,dfs搜索每种状态之间的转移。

    这样一共有2^12种状态,显然进行矩阵快速幂优化时会超时,便考虑减少状态。

    进行两遍bfs,分别为初始状态可以到达的状态,和可以到达终止状态的状态。

    同时出现在两次bfs中的状态即为有效状态,一共有141种。

    这样就可以跑出来了。

    未加矩阵快速幂 50分

     1 const dx:array[1..8,1..3] of longint=
     2     ((-1,0,0),(-1,0,0),(1,0,0),(0,1,0),(-1,0,0),(-1,1,0),(0,1,0),(-1,0,1));
     3     dy:array[1..8,1..3] of longint=
     4     ((0,1,0),(0,-1,0),(0,-1,0),(1,0,0),(0,1,-1),(0,0,-1),(1,0,-1),(0,1,0));
     5     mo=65521;
     6 var n,m,lx,i,j,k:longint;
     7     a:array[0..10,0..10] of longint;
     8     g:array[0..5000,0..5000] of longint;
     9     dp:array[0..200,0..5000] of longint;
    10 function ok(x,y:longint):boolean; inline;
    11 begin
    12     if (x>=1) and (x<=3) and (y>=1) and (y<=m) and (a[x,y]=0) then exit(true);
    13     exit(false);
    14 end;
    15 function check(y,j:longint):boolean;
    16 var i,x:longint;
    17 begin
    18     x:=2;
    19     if not ok(x,y) then exit(false);
    20     for i:=1 to 3 do
    21         if not ok(x+dx[j,i],y+dy[j,i]) then exit(false);
    22     exit(true);
    23 end;    
    24 procedure fill(y,j,cl:longint);
    25 var i,x:longint;
    26 begin
    27     x:=2;
    28     a[x,y]:=cl;
    29     for i:=1 to 3 do
    30         a[x+dx[j,i],y+dy[j,i]]:=cl;
    31 end;    
    32 procedure dfs(x,lt:longint);
    33 var i,j,sum:longint;
    34 begin
    35     if x=m+1 then
    36     begin
    37         for i:=1 to m do if a[1,i]=0 then exit; //保证了DP的正确性
    38         sum:=0;
    39         for i:=2 to 3 do 
    40             for j:=1 to m do
    41                 sum:=sum*2+a[i,j];
    42         inc(g[lt][sum]);
    43         exit;
    44     end;
    45     dfs(x+1,lt);
    46     for i:=1 to 8 do
    47         if check(x,i) then
    48         begin
    49             fill(x,i,1);
    50             dfs(x+1,lt);
    51             fill(x,i,0);
    52         end;
    53 end;
    54 begin
    55     assign(input,'tile.in');reset(input);
    56     assign(output,'tile.out');rewrite(output);
    57     readln(n,m);
    58     for i:=0 to 1<<(2*m)-1 do
    59     begin
    60         for j:=1 to m do 
    61             if i and (1<<(m*2-j))>0 then a[1,j]:=1 else a[1,j]:=0; 
    62         for j:=1 to m do 
    63             if i and (1<<(m-j))>0 then a[2,j]:=1 else a[2,j]:=0; 
    64         dfs(1,i);
    65     end;
    66     dp[1][(1<<m-1)<<m]:=1;
    67     for i:=2 to n+1 do    
    68         for j:=0 to 1<<(2*m)-1 do
    69             for k:=0 to 1<<(2*m)-1 do
    70                 dp[i][j]:=(dp[i][j]+dp[i-1][k]*g[k][j]) mod mo;
    71     writeln(dp[n+1][(1<<m-1)<<m]);
    72     close(input);
    73     close(output);
    74 end.

    AC 代码1:

      1 const dx:array[1..8,1..3] of longint=
      2     ((-1,0,0),(-1,0,0),(1,0,0),(0,1,0),(-1,0,0),(-1,1,0),(0,1,0),(-1,0,1));
      3     dy:array[1..8,1..3] of longint=
      4     ((0,1,0),(0,-1,0),(0,-1,0),(1,0,0),(0,1,-1),(0,0,-1),(1,0,-1),(0,1,0));
      5     mo=65521;
      6 type arr=array[0..500,0..500] of int64;
      7 var i,j,k,m,xh:longint;
      8     n:int64;
      9     a:array[0..100,0..100] of longint;
     10     g:array[0..4200,0..4200] of longint;
     11     b:array[0..100000] of longint;
     12     v1,v2:array[0..4200] of boolean;
     13     pos:array[0..4200] of int64;
     14     mat,f:arr;
     15 function ok(x,y:longint):boolean; inline;
     16 begin
     17     if (y>=1) and (y<=m) and (a[x,y]=0) then exit(true);
     18     exit(false);
     19 end;
     20 function check(y,j:longint):boolean; inline;
     21 var i,x:longint;
     22 begin
     23     x:=2;
     24     if not ok(x,y) then exit(false);
     25     for i:=1 to 3 do
     26         if not ok(x+dx[j,i],y+dy[j,i]) then exit(false);
     27     exit(true);
     28 end;    
     29 procedure fill(y,j,cl:longint); inline;
     30 var i,x:longint;
     31 begin
     32     x:=2;
     33     a[x,y]:=cl;
     34     for i:=1 to 3 do
     35         a[x+dx[j,i],y+dy[j,i]]:=cl;
     36 end;    
     37 procedure dfs(x,lt:longint);
     38 var i,j,sum:longint;
     39 begin
     40     if x=m+1 then
     41     begin
     42         for i:=1 to m do if a[1,i]=0 then exit;
     43         sum:=0;
     44         for i:=2 to 3 do 
     45             for j:=1 to m do
     46                 sum:=sum*2+a[i,j];
     47         inc(g[lt][sum]);
     48         exit;
     49     end;
     50     dfs(x+1,lt);
     51     for i:=1 to 8 do
     52         if check(x,i) then
     53         begin
     54             fill(x,i,1);
     55             dfs(x+1,lt);
     56             fill(x,i,0);
     57         end;
     58 end;
     59 procedure bfs;
     60 var i,j,l,r,x,y:longint;
     61 begin
     62     fillchar(v1,sizeof(v1),false);
     63     fillchar(v2,sizeof(v2),false);
     64     l:=1; r:=1; b[1]:=(1<<m-1)<<m; v1[(1<<m-1)<<m]:=true;
     65     while l<=r do
     66     begin
     67         x:=b[l];
     68         for y:=0 to (1<<(m*2)-1) do
     69             if (g[x,y]>0) and not v1[y] then 
     70             begin
     71                 v1[y]:=true;
     72                 inc(r);
     73                 b[r]:=y;
     74             end;
     75         inc(l);
     76     end;
     77     l:=1; r:=1; b[1]:=(1<<m-1)<<m; v2[(1<<m-1)<<m]:=true;
     78     while l<=r do
     79     begin
     80         x:=b[l];
     81         for y:=0 to 1<<(m*2)-1 do
     82             if (g[y,x]>0) and not v2[y] then 
     83             begin
     84                 v2[y]:=true;
     85                 inc(r);
     86                 b[r]:=y;
     87             end;
     88         inc(l);
     89     end;
     90     xh:=0;
     91     for i:=0 to 1<<(m*2)-1 do
     92         if v1[i] and v2[i] then
     93         begin
     94             inc(xh);
     95             pos[i]:=xh;
     96         end;
     97     for i:=1 to r do
     98         for j:=1 to r do
     99             mat[pos[b[i]],pos[b[j]]]:=g[b[i],b[j]];
    100 end;
    101 operator *(a,b:arr) c:arr; inline;
    102 var i,j,k:longint;
    103 begin
    104     for i:=1 to xh do
    105         for j:=1 to xh do
    106         begin
    107             c[i,j]:=0;
    108             for k:=1 to xh do
    109                 c[i,j]:=(c[i,j]+a[i,k]*b[k,j]);
    110             c[i,j]:=c[i,j] mod mo;
    111         end;
    112     exit(c);
    113 end;
    114 begin
    115     assign(input,'tile.in');reset(input);
    116     assign(output,'tile.out');rewrite(output);
    117     readln(n,m);
    118     for i:=0 to 1<<(2*m)-1 do
    119     begin
    120         for j:=1 to m do 
    121             if i and (1<<(m*2-j))>0 then a[1,j]:=1 else a[1,j]:=0; 
    122         for j:=1 to m do 
    123             if i and (1<<(m-j))>0 then a[2,j]:=1 else a[2,j]:=0; 
    124         dfs(1,i);
    125     end;
    126     {dp[1][(1<<m-1)<<m]:=1;
    127     for i:=2 to n+1 do    
    128         for j:=0 to 1<<(2*m)-1 do
    129             for k:=0 to 1<<(2*m)-1 do
    130                 dp[i][j]:=(dp[i][j]+dp[i-1][k]*g[k][j]) mod mo;}
    131     bfs;
    132     for i:=1 to xh do f[i,i]:=1;
    133     writeln(xh);
    134     while n>0 do
    135     begin
    136         if n and 1=1 then f:=f*mat;
    137         mat:=mat*mat;
    138         n:=n>>1;
    139     end;
    140     writeln(f[pos[(1<<m-1)<<m]][pos[(1<<m-1)<<m]]);
    141     close(input);
    142     close(output);
    143 end.

    AC 代码2 :(Orz rpCardinal)

      1 #include <cstdio>
      2 #include <cstring>
      3 #define P 65521
      4 
      5 #ifdef _WIN32
      6 #define ll "%I64d"
      7 #else
      8 #define ll "%lld"
      9 #endif
     10 
     11 int m,M,ST,N,q[5000],h[5000],pos[5000];
     12 long long n,g[4096][4096],t[150][150];
     13 bool b[3][10],v1[5000],v2[5000];
     14 
     15 struct matrix
     16 {
     17     long long a[150][150];
     18     matrix() {memset(a,0,sizeof(a));}
     19     void one() {for (int i=1;i<=N;++i) a[i][i]=1;}
     20     matrix& operator*=(const matrix &B)
     21     {
     22         memset(t,0,sizeof(t));
     23         for (int i=1;i<=N;++i)
     24             for (int j=1;j<=N;++j)
     25                 for (int k=1;k<=N;++k)
     26                     t[i][j]=(t[i][j]+a[i][k]*B.a[k][j])%P;
     27         memcpy(a,t,sizeof(a)); return *this;
     28     }
     29 }A,R;
     30 
     31 bool can(int i,int j)
     32 {return i>=0&&i<3&&j>=0&&j<m&&!b[i][j];}
     33 
     34 bool check(int k,int i)
     35 {
     36     switch (k)
     37     {
     38         case 1:return can(1,i)&&can(1,i+1)&&can(0,i);
     39         case 2:return can(1,i)&&can(1,i+1)&&can(2,i);
     40         case 3:return can(1,i)&&can(1,i-1)&&can(2,i);
     41         case 4:return can(1,i)&&can(1,i-1)&&can(0,i);
     42         case 5:return can(1,i)&&can(0,i)&&can(2,i)&&can(1,i+1);
     43         case 6:return can(1,i)&&can(2,i)&&can(1,i-1)&&can(1,i+1);
     44         case 7:return can(1,i)&&can(0,i)&&can(2,i)&&can(1,i-1);
     45         case 8:return can(1,i)&&can(0,i)&&can(1,i-1)&&can(1,i+1);
     46         default:return 0;
     47     }
     48 }
     49 
     50 bool fill(int k,int i,int v)
     51 {
     52     switch (k)
     53     {
     54         case 1:return b[1][i]=b[1][i+1]=b[0][i]=v;
     55         case 2:return b[1][i]=b[1][i+1]=b[2][i]=v;
     56         case 3:return b[1][i]=b[1][i-1]=b[2][i]=v;
     57         case 4:return b[1][i]=b[1][i-1]=b[0][i]=v;
     58         case 5:return b[1][i]=b[0][i]=b[2][i]=b[1][i+1]=v;
     59         case 6:return b[1][i]=b[2][i]=b[1][i-1]=b[1][i+1]=v;
     60         case 7:return b[1][i]=b[0][i]=b[2][i]=b[1][i-1]=v;
     61         case 8:return b[1][i]=b[0][i]=b[1][i-1]=b[1][i+1]=v;
     62         default:return 0;
     63     }
     64 }
     65 
     66 void dfs(int dep,int last)
     67 {
     68     if (dep>m)
     69     {
     70         for (int i=0;i<m;++i) if (!b[0][i]) return;
     71         int next=0;
     72         for (int i=2;i;--i)
     73             for (int j=m-1;j>=0;--j)
     74                 next=next*2+b[i][j];
     75         ++g[last][next]; return;
     76     }
     77     dfs(dep+1,last);
     78     for (int i=1;i<=8;++i)
     79         if (check(i,dep))
     80         {fill(i,dep,1); dfs(dep+1,last); fill(i,dep,0);}
     81 }
     82 
     83 void bfs()
     84 {
     85     int l=0,r=0; q[++r]=ST; v1[ST]=1;
     86     while (l<r)
     87     {
     88         int x=q[++l];
     89         for (int y=0;y<M;++y)
     90             if (g[x][y]&&!v1[y]) {v1[y]=1; q[++r]=y;}
     91     }
     92     l=r=0; q[++r]=ST; v2[ST]=1;
     93     while (l<r)
     94     {
     95         int x=q[++l];
     96         for (int y=0;y<M;++y)
     97             if (g[y][x]&&!v2[y]) {v2[y]=1; q[++r]=y;}
     98     }
     99     for (int i=0;i<M;++i)
    100         if (v1[i]&&v2[i]) {h[++N]=i; pos[i]=N;}
    101     for (int i=0;i<M;++i)
    102         for (int j=0;j<M;++j)
    103             A.a[pos[i]][pos[j]]=g[i][j];
    104 }
    105 
    106 void pow(long long b)
    107 {while (b) {if (b&1) R*=A; A*=A; b>>=1;}}
    108 
    109 int main()
    110 {
    111     freopen("tile.in","r",stdin);
    112     freopen("tile.out","w",stdout);
    113     scanf(ll "%d",&n,&m); M=1<<(2*m); ST=(1<<m)-1;
    114     for (int st=0;st<M;++st)
    115     {
    116         for (int i=0;i<m;++i) b[0][i]=(st>>i)&1;
    117         for (int i=0;i<m;++i) b[1][i]=(st>>(i+m))&1;
    118         dfs(0,st);
    119     }
    120     bfs(); R.one(); pow(n);
    121     printf(ll "
    ",R.a[pos[ST]][pos[ST]]);
    122     fclose(stdin); fclose(stdout);
    123     return 0;
    124 }
  • 相关阅读:
    阿里消息队列中间件 RocketMQ 源码分析 —— Message 拉取与消费(上)
    数据库中间件 ShardingJDBC 源码分析 —— SQL 解析(三)之查询SQL
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 解析(六)之删除SQL
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 解析(五)之更新SQL
    消息队列中间件 RocketMQ 源码分析 —— Message 存储
    源码圈 300 胖友的书单整理
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 路由(一)分库分表配置
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 解析(四)之插入SQL
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 路由(二)之分库分表路由
    C#中Math类的用法
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/4550248.html
Copyright © 2011-2022 走看看