hdu 5766 Filling 轮廓线dp burnside
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
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
00100 0110 0011
00000 0000 0000
00000
写轮廓线的时候有个地方要注意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