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

hdu 5766 Filling 轮廓线dp burnside

时间:2016-07-31 01:46:53      阅读:496      评论:0      收藏:0      [点我收藏+]

标签:

Filling 

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=5766

Description

The board is a rectangle of unit cells with N rows and N columns. At first, cells are empty. ?? has infinite blocks with the size of 2*2. ?? can put blocks in the board as long as no two blocks overlap. ?? wants to know how many different ways to fill the board, not necessary full. Two ways are consider same if they are same by rotating.

Input

The first line of the input gives the number of test cases T; T test cases follow.
Each test case consists of one integers N, as described on the description above.

limits
T <= 20
1 <= N <= 20

Output

For each test case, output one line containing “Case #x: y” (without quotes) , where x is the test case number (starting from 1) and y is the answer you get for that case, since the answer may be too large, you should output the it modulo 1000000007 (1e9 + 7).
 

Sample Input

5
1
2
3
4
5

Sample Output

Case #1: 1
Case #2: 2
Case #3: 2
Case #4: 12
Case #5: 84

hint

In forth case, we have 12 different ways.(0 denotes unfilled,1 denoted filled)
0000   1100   0110   0000   1111   0000   1100   1100   1100   1111   1111   1111
0000   1100   0110   0110   1111   1111   1111   1100   1100   1111   1111   1111
0000   0000   0000   0110   0000   1111   0011   0011   0110   1100   0110   1111
0000   0000   0000   0000   0000   0000   0000   0011   0110   1100   0110   1111

题意:

n*n的格子里放2*2的块,相互不重叠,问旋转同构下的方案数

题解:

旋转同构很好判,根据bunrside引理,就是转0,90,180,270度下旋转不变的情况数求和除4。转90和转270是一样的,所以一共只有三种情况。

转0度:

  就是一个n*n的格子,2*2的块不能放出限制,直接画出mask,轮廓线dp

  以4*4为例,它的边界mask为:

  111111

  100001

  100001

  100001

  100001

  111111

转90度:

  转90度的情况最为复杂,总的来说就是枚举中间十字放2*2的情况,再对一个角落跑轮廓线dp。以方便考虑,我们考虑右下角的1/4块

  n为奇数时,中间的m[n/2+1][n/2+1]不能放,边界左上角不会冲突,那么直接枚举2n/2的边界放置情况,顺便判是否两个两个在一起。

  n为偶数时,如果有一个放在边界左上角,必然冲突不能旋转同构。所有的合法情况是不管那最左边的那个,直接枚举2n/2的边界放置情况,顺便判edge>>1是否两个两个在一起。

  0000  0000

  0011  0110

  0011  0110

  0000  0000

转180度

  我考虑下半面

  n为奇数时,中间的m[n/2+1][n/2+1]不能放,注意边界左边低一格

  n为偶数时,有两种情况,枚举边界的时候要注意,1是edge合法,2是edge>>1合法

  11111      0000  0000

  11100    0110  0011

  00000    0110  0011

  00000    0000  0000

写轮廓线的时候有个地方要注意mask[X+1][t]

void dfs(LL st,int t,LL dp)    //st之前状态,code上行状态,mask边界,当前在(X,t)
{
    if(t>=n+1)return;
    if(!mask[X][t]&&!mask[X][t+1]&&!code[t]&&!code[t+1]&&!mask[X+1][t])
    {
        hm[f^1].push(st^(1<<t)^(1<<(t+1)),dp);
        dfs(st^(1<<t)^(1<<(t+1)),t+2,dp);
    }
    dfs(st,t+1,dp);
}

最后写完打表就好了

第一次写轮廓线,写了很久,各种坑。。

代码

  1 //#include <bits/stdc++.h>
  2 #include <stdio.h>
  3 #include <iostream>
  4 #include <string.h>
  5 #include <math.h>
  6 #include <stdlib.h>
  7 #include <limits.h>
  8 #include <algorithm>
  9 #include <queue>
 10 #include <vector>
 11 #include <set>
 12 #include <map>
 13 #include <stack>
 14 #include <bitset>
 15 #include <string>
 16 #include <time.h>
 17 using namespace std;
 18 long double esp=1e-11;
 19 //#pragma comment(linker, "/STACK:1024000000,1024000000")
 20 #define fi first
 21 #define se second
 22 #define all(a) (a).begin(),(a).end()
 23 #define cle(a) while(!a.empty())a.pop()
 24 #define mem(p,c) memset(p,c,sizeof(p))
 25 #define mp(A, B) make_pair(A, B)
 26 #define pb push_back
 27 #define lson l , m , rt << 1
 28 #define rson m + 1 , r , rt << 1 | 1
 29 typedef long long int LL;
 30 const long double PI = acos((long double)-1);
 31 const LL INF=0x3f3f3f3fll;
 32 const int MOD =1000000007ll;
 33 const int maxn=11000;
 34 
 35 LL inv4=250000002ll;
 36 const int MAXD=15;
 37 const int HASH=30007;
 38 const int STATE=1<<20;
 39 struct HASHMAP
 40 {
 41     int head[HASH],next[STATE],sz;
 42     LL state[STATE];
 43     LL dp[STATE];
 44     void init()
 45     {
 46         sz=0;
 47         memset(head,-1,sizeof(head));
 48     }
 49     void push(LL st,LL ans)
 50     {
 51         int i;
 52         int h=st%HASH;
 53         for(i=head[h];i!=-1;i=next[i])//这里要注意是next
 54           if(state[i]==st)
 55           {
 56               dp[i]=(dp[i]+ans)%MOD;
 57               //dp[i]+=ans;
 58               return;
 59           }
 60         state[sz]=st;
 61         dp[sz]=ans;
 62         next[sz]=head[h];
 63         head[h]=sz++;
 64     }
 65 }hm[2];
 66 int n;
 67 bool mask[22][22];
 68 int f,code[22],X;
 69 void decode(LL state)
 70 {
 71     for(int x=1;x<=n;x++)
 72         code[x]=((state>>x)&1);
 73     code[0]=code[n+1]=1;
 74 }
 75 void dfs(LL st,int t,LL dp)
 76 {
 77     if(t>=n+1)return;
 78     if(!mask[X][t]&&!mask[X][t+1]&&!code[t]&&!code[t+1]&&!mask[X+1][t])
 79     {
 80         hm[f^1].push(st^(1<<t)^(1<<(t+1)),dp);
 81         dfs(st^(1<<t)^(1<<(t+1)),t+2,dp);
 82     }
 83     dfs(st,t+1,dp);
 84 }
 85 bool check(int s,int l)
 86 {
 87     for(int x=0;x<l;x++)
 88         if((s>>x)&1)
 89         {
 90             if((s>>(x+1))&1)
 91             {
 92                 x++;
 93                 continue;
 94             }
 95             else
 96                 return 0;
 97         }
 98     return 1;
 99 }
100 LL lkx(int a,int b,int n)
101 {
102     hm[0].init();
103     hm[0].push(0,1);
104     f=0;
105     for(int x=a;x<=n;x++)
106     {
107         X=x;
108         hm[f^1].init();
109         for(int k=0;k<hm[f].sz;k++)
110         {
111             decode(hm[f].state[k]);
112             LL dp=hm[f].dp[k];
113             hm[f^1].push(0,dp);
114             dfs(0,b,dp);
115         }
116         f^=1;
117     }
118     for(int k=0;k<hm[f].sz;k++)
119         if(hm[f].state[k]==0)
120             return hm[f].dp[k]%MOD;
121 }
122 int main()
123 {
124     //freopen("in.txt", "r", stdin);
125     //freopen("inlay.in", "r", stdin);
126     //freopen("out.txt", "w", stdout);      //%I64d
127     //vector<int>::iterator iter;
128     //memset(m,0,sizeof(int));
129     //for(int x=1;x<=n;x++)
130     //for(int y=1;y<=n;y++)
131     //scanf("%d",&a);
132     //printf("%d\n",ans);
133     for(n=1;n<=20;n++)
134     {
135         //***********0
136         mem(mask,0);
137         for(int x=0;x<=n+1;x++)
138         {
139             if(x==0||x==n+1)
140                 for(int y=0;y<=n+1;y++)
141                     mask[x][y]=1;
142             else
143                 mask[x][0]=mask[x][n+1]=1;
144         }
145         LL ans=0;
146         ans+=lkx(1,1,n);
147         //printf("0 %d %lld\n",n,ans);    ans=0;
148         //***********90 270
149         for(int s=0;s<(1<<(n/2));s++)
150         {
151             int odd=n&1;
152             if(odd&&!check(s,n/2))continue;
153             if(!odd&&!check(s>>1,n/2-1))continue;
154             mem(mask,0);
155             for(int x=n/2;x<=n+1;x++)
156             {
157                 if(x==n/2||x==n+1)
158                     for(int y=0;y<=n+1;y++)
159                         mask[x][y]=1;
160                 else
161                     mask[x][n/2+odd]=mask[x][n+1]=1;
162             }
163             for(int x=n/2+1+odd;x<=n;x++)
164                 mask[x][n/2+1+odd]=mask[n/2+1][x]=(s>>(x-n/2-1-odd))&1;
165             ans+=lkx(n/2+1,n/2+1+odd,n)*2;
166         }
167         //printf("1 %d %lld\n",n,ans);    ans=0;
168         //***********180
169         for(int s=0;s<(1<<(n/2));s++)
170         {
171             int odd=n&1;
172             if(odd&&!check(s,n/2))continue;
173             if(!odd&&!(check(s,n/2)||check(s>>1,n/2-1)))continue;
174             mem(mask,0);
175             for(int x=n/2;x<=n+1;x++)
176             {
177                 if(x==n/2||x==n+1)
178                     for(int y=0;y<=n+1;y++)
179                         mask[x][y]=1;
180                 else
181                     mask[x][0]=mask[x][n+1]=1;
182             }
183             if(odd)
184             for(int x=1;x<=n/2+1;x++)
185                 mask[n/2+1][x]=1;
186             for(int x=n/2+1+odd;x<=n;x++)
187                 mask[n/2+1+odd][n+1-x]=mask[n/2+1][x]=(s>>(x-n/2-1-odd))&1;
188             ans+=lkx(n/2+1,1,n);
189         }
190         //printf("3 %d %lld\n",n,ans);
191         printf(",%I64d",ans%MOD*inv4%MOD);
192     }
193 
194     return 0;
195 }

值为

LL ans[25]={1,1,2,2,12,84,1641,50788,3183091,338785462,429880385,948920428,392930107,842384602,
36468923,534250025,693507546,311288183,320259213,232751393,866290697};



2016-07-31

hdu 5766 Filling 轮廓线dp burnside

标签:

原文地址:http://www.cnblogs.com/femsub/p/5722136.html

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