• hdu5079


    这道题的难点在于思考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
    ",ans[i]);
    94     }
    95 }
    View Code
  • 相关阅读:
    bootstrap-table实现分页、导出数据至excel
    Python求多个list的交集、并集、差集 & list 排序
    JS
    python 格式化输出(% VS format)
    pyqt5_实例:修改xml文件中节点值
    博客迁移
    Reverse is Multiplex, You Need PinTools.
    ISCC2018_leftleftrightright-Writeup
    如何在linux主机上运行/调试 arm/mips架构的binary
    强网杯2018
  • 原文地址:https://www.cnblogs.com/phile/p/6378483.html
Copyright © 2020-2023  润新知