码迷,mamicode.com
首页 > 其他好文 > 详细

瓷砖铺放 (状压DP+矩阵快速幂)

时间:2015-06-03 23:07:11      阅读:349      评论:0      收藏:0      [点我收藏+]

标签:

未加矩阵快速幂 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 #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 "\n",R.a[pos[ST]][pos[ST]]);
122     fclose(stdin); fclose(stdout);
123     return 0;
124 }

 

瓷砖铺放 (状压DP+矩阵快速幂)

标签:

原文地址:http://www.cnblogs.com/rpSebastian/p/4550248.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!