bzoj2331: [SCOI2011]地板

来源:互联网 发布:svs视频分享网站seo 编辑:程序博客网 时间:2024/04/26 06:04

2331: [SCOI2011]地板

Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 1298 Solved: 556
[Submit][Status][Discuss]
Description

lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?
需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。

Input

输入的第一行包含两个整数,R和C,表示客厅的大小。
接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。
Output

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

2 2

*_

__

Sample Output

1

HINT

R*C<=100

插头DP的好题啊————对于我来说
第一次做这种变形。。
以前都是什么回路什么的
其实这题和别的也差不多。。
但插头的意义要改一下

0表示无插头,1表示有插头没有拐弯,2表示有插头且已经拐弯

但由于我之前的插P哈希模板是学习TYB大佬的,有点慢,TYB大佬也说不行了,于是改进了一下模板,运用了邻接表,就快多了。。前排膜拜TYB大佬

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cstring>using namespace std;const int N=105;const int mod=100037;const int MOD=20110520;int r,c;bool map[N][N];int xx,yy;void init (){    memset(map,false,sizeof(map));    scanf("%d%d",&r,&c);    for (int u=1;u<=r;u++)    {        char ss[105];        scanf("%s",ss+1);        for (int i=1;i<=c;i++)        {            if (ss[i]=='_')            {                if (r<c)//将来要交换的啦                     map[i][u]=true,xx=i,yy=u;                else                    map[u][i]=true,xx=u,yy=i;            }        }    }    if (r<c) swap(r,c);}int sta[2][mod*10],num[2],list[2][mod*10],now;int last[mod+10],len=0;struct Edge{int y,next;}e[210000];int get(int s,int p){return (s>>((p-1)*2))&3;}void change(int &s,int p,int v){    s^=get(s,p)<<((p-1)*2);    s^=(v)<<((p-1)*2);}void add(int st,int sum)  {      int x=st%mod;    for(int i=last[x];i;i=e[i].next)      if(list[now][e[i].y]==st)    {        sta[now][e[i].y]+=sum;        sta[now][e[i].y]%=MOD;          return;    }    num[now]++;      list[now][num[now]]=st;     sta[now][num[now]]=sum;    int t=++len;    e[t].y=num[now],e[t].next=last[x],last[x]=t;  }int ans=0;void solve (){    now=0;sta[0][1]=1;num[0]=1;list[0][1]=0;    for (int u=1;u<=r;u++)    {        for (int i=1;i<=c;i++)        {            now^=1;            num[now]=0;len=0;            memset(last,0,sizeof(last));            for (int k=1;k<=num[now^1];k++)            {                int st=list[now^1][k];                int sum=sta[now^1][k];                int p=get(st,i),q=get(st,i+1);                if (u==xx&&i==yy)//已经到达“终点”了                 {                    if (p+q==2)//这里有三种情况-->1.p=q=1,表示在这个点连起来   2.p=0,q=2,表示上面下来   3.和2反过来                    {                        ans=ans+sum;                        ans%=MOD;                    }                    continue;                }                else if (map[u][i]==false)                {                    if (p+q==0)//这里就是两个0啦                        add(st,sum);                    continue;                }                else if (p+q==0)                {                    int st2=st;                    if (map[u+1][i]) change(st2,i,1),add(st2,sum);                    st2=st;                    if (map[u][i+1]) change(st2,i+1,1),add(st2,sum);                    st2=st;                    if (map[u][i+1]&&map[u+1][i])                           change(st2,i,2),change(st2,i+1,2),add(st2,sum);                }                else if (p==0&&q!=0)                {                    int st2=st;                    if (q==1)                    {                        if (map[u+1][i]) change(st2,i,1),change(st2,i+1,0),add(st2,sum);                        st2=st;                        if (map[u][i+1]) change(st2,i+1,2),add(st2,sum);                    }                    else                    {                        if (map[u+1][i]) change(st2,i,2),change(st2,i+1,0),add(st2,sum);                        st2=st;                        change(st2,i+1,0);add(st2,sum);                    }                }                else if (p!=0&&q==0)                {                    int st2=st;                    if (p==1)                    {                        if (map[u][i+1]) change(st2,i,0),change(st2,i+1,1),add(st2,sum);                        st2=st;                        if (map[u+1][i]) change(st2,i,2),add(st2,sum);                    }                    else                    {                        if (map[u][i+1]) change(st2,i,0),change(st2,i+1,2),add(st2,sum);                        st2=st;                        change(st2,i,0);add(st2,sum);                    }                }                else if (p==1&&q==1)                {                    change(st,i,0);change(st,i+1,0);                    add(st,sum);                }            }        }        for (int k=1;k<=num[now];k++)    list[now][k]<<=2;    }}int main(){    init();    solve();    printf("%d\n",ans);    return 0;}
原创粉丝点击