【SCOI2011】bzoj2331 地板

来源:互联网 发布:安索夫矩阵 编辑:程序博客网 时间:2024/04/25 00:07

Description

lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?

需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。

Input

输入的第一行包含两个整数,R和C,表示客厅的大小。

接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。 Output

输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。

插头dp。
几个需要注意的地方:
哈希表记录被更新的状态,只用这些状态转移。
总共要保存c+1个插头。
行末不能向右接插头。
记录了插头代表“已经插进来”,不能停在旁边的格子。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int mod=20110520,p=100007;char s[110][110];int fir[2][100010],ne[2][200010],val[2][200010],ans[2][200010],last[2][100010],tot,cur,y;int find(int x){    int y=x%p;    if (last[cur&1][y]<cur)    {        fir[cur&1][y]=0;        last[cur&1][y]=cur;    }    for (int i=fir[cur&1][y];i;i=ne[cur&1][i])        if (val[cur&1][i]==x) return i;    tot++;    ne[cur&1][tot]=fir[cur&1][y];    fir[cur&1][y]=tot;    val[cur&1][tot]=x;    ans[cur&1][tot]=0;    return tot;}void upd(int xx){    int z=find(xx);    ans[cur&1][z]+=y;    ans[cur&1][z]%=mod;}int main(){    int r,c,x,x0,x1;    scanf("%d%d",&r,&c);    for (int i=0;i<r;i++) scanf("%s",s[i]);    if (r<c)    {        for (int i=0;i<c;i++)            for (int j=i+1;j<c;j++)                swap(s[i][j],s[j][i]);        swap(r,c);    }    cur=0;    find(0);    ans[0][1]=1;    for (int i=0;i<r;i++)    {        for (int j=0;j<c;j++)        {            cur++;            tot=0;            for (int k=0;k<p;k++)            if (last[cur&1^1][k]==cur-1)            for (int l=fir[cur&1^1][k];l;l=ne[cur&1^1][l])            {                x=val[cur&1^1][l];                y=ans[cur&1^1][l];                x0=x&3;                x1=(x>>2*c)&3;                if (s[i][j]=='*')                {                    if (!(x0&3)&&!(x1&3)) upd(x>>2);                    continue;                }                if (x0&2)                {                    if (x1&2) upd((x>>2)^(2<<2*(c-1)));                    if (!(x1&3))                    {                        upd((x>>2)|(2<<2*(c-1)));                        if (j<c-1) upd((x>>2)|(1<<2*c));                    }                }                if (x0&1)                {                    if (!(x1&3))                    {                        upd(x>>2);                        upd((x>>2)|(1<<2*(c-1)));                    }                }                if (!(x0&3))                {                    if (!(x1&3))                    {                        if (j<c-1) upd((x>>2)|(2<<2*c));                        if (j<c-1) upd((x>>2)|(1<<2*c)|(1<<2*(c-1)));                        upd((x>>2)|(2<<2*(c-1)));                    }                    if (x1&1)                    {                        upd((x>>2)^(1<<2*(c-1)));                        if (j<c-1) upd((x>>2)^(1<<2*(c-1))|(1<<2*c));                    }                    if (x1&2)                    {                        if (j<c-1) upd(((x>>2)^(2<<2*(c-1)))|(2<<2*c));                        upd((x>>2)^(3<<2*(c-1)));                    }                }            }        }    }    printf("%d\n",ans[cur&1][find(0)]);}
0 0
原创粉丝点击