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 }
  • 相关阅读:
    (转载)Linux系统中分离线程的使用
    (转载)Vim的几种模式介绍
    (转载)Linux下检查内存泄漏、系统性能的系列工具
    (转载)Linux 僵尸进程与孤儿进程
    (转载)valgrind,好东西,一般人我不告诉他~~ 选项
    (转载)Linux进程组、作业、会话的理解
    Open a file, and then readin a file tcl tk
    save vars and arrays
    itcl class example
    constructor with args tcl tk
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/4550248.html
Copyright © 2011-2022 走看看