这道题的难点在于思考dp表示什么

首先可以令ans[len]表示白色子矩阵边长最大值大于等于len的方案数则ans[len]-ans[len+1]就是beautifulness为len的方案数

白色子矩阵边长最大值大于等于len的方案数=总方案-白色子矩阵边长最大值小于len的方案数

经过这样的转化,我们就好dp了,我们先穷举len

令f[i][st]表示到第i行,状态为st的白色子矩阵边长最大值小于len的方案数

怎么设计状态呢,由于要保证白色子矩阵边长最大值小于len

我们维护一个n-len+1的len进制数,第j位表示(i,j)~(i,j+len-1)中向上延伸的白色格子数的最小值

这样我们二进制穷举每行的涂色方法就可以转移状态了

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 const int mo=1e9+7;
 6 int d[10],a[10],ans[10],v[10],n;
 7 char s[10];
 8 void inc(int &a,int b)
 9 {
10     a+=b;
11     if (a>mo) a-=mo;
12 }
13 
14 struct node
15 {
16     int st[200010],c[200010],len;
17     void clr()
18     {
19         for (int i=1; i<=len; i++) c[st[i]]=0;
20         len=0;
21     }
22     void push(int nw,int w)
23     {
24         if (!c[nw]) st[++len]=nw;
25         inc(c[nw],w);
26     }
27 } f[2];
28 int main()
29 {
30     int cas;
31     scanf("%d",&cas);
32     f[0].len=f[1].len=0;
33     while (cas--)
34     {
35         int m=1;
36         scanf("%d",&n);
37         for (int i=1; i<=n; i++)
38         {
39             scanf("%s",s);
40             a[i]=0;
41             for (int j=0; j<n; j++)
42                 if (s[j]=='o') m=m*2%mo;
43                 else a[i]|=(1<<j);
44         }
45         ans[0]=1;
46         ans[1]=(m-1+mo)%mo;
47         for (int l=2; l<=n; l++)
48         {
49             int p=0,k=n+1-l;
50             d[0]=1;
51             for (int i=1; i<=n; i++) d[i]=d[i-1]*l;
52             f[0].clr();
53             f[0].push(0,1);
54             for (int i=1; i<=n; i++)
55             {
56                 p^=1;
57                 f[p].clr();
58                 for (int cur=0; cur<(1<<n); cur++)
59                 {
60                     if (cur&a[i]) continue;
61                     for (int r=0; r<k; r++) v[r]=0;
62                     for (int r=0; r<n; r++)
63                     {
64                         if ((cur>>r)&1) continue;
65                         for (int j=0; j<k; j++)
66                             if (r>=j&&r<j+l) v[j]=1;
67                     }
68                     for (int j=1; j<=f[p^1].len; j++)
69                     {
70                         int pre=f[p^1].st[j],nw=0;
71                         int w=f[p^1].c[pre];
72                         for (int r=0; r<k; r++)
73                         {
74                             int x=pre%l; pre/=l;
75                             if (v[r]) continue;
76                             if (x==l-1) {nw=-1; break;}
77                             nw+=(x+1)*d[r];
78                         }
79                         if (nw>-1) f[p].push(nw,w);
80                     }
81                 }
82             }
83             ans[l]=0;
84             for (int i=1; i<=f[p].len; i++)
85             {
86                 int x=f[p].st[i];
87                 inc(ans[l],f[p].c[x]);
88             }
89             ans[l]=(m-ans[l]+mo)%mo;
90             ans[l-1]=(ans[l-1]-ans[l]+mo)%mo;
91         }
92         for (int i=0; i<=n; i++)
93             printf("%d\n",ans[i]);
94     }
95 }
View Code

 

posted on 2017-02-08 15:41  acphile  阅读(237)  评论(0编辑  收藏  举报