瓷砖铺放 (状压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 }
原文地址:https://www.cnblogs.com/rpSebastian/p/4550248.html