博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

bzoj:2331: [SCOI2011]地板

Description

 

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

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

Input

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

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

Output

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

Sample Input

2 2

*_

__

Sample Output

1
 
 
插头dp……蒟蒻的模板慢得要死……用0表示无插头,1表示有未拐的插头,2表示已拐的插头……
然后转移就自己YY一下就好了……
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=20110520;
const int MAXN=177147;
int i;
struct na{
    int x,z;
    na(int xx,int zz):x(xx),z(zz){}
};
int n,m,x,y,z,a[21],k,p1,p2,en,t;
bool map[101][101];
int f[2][MAXN+1],ans=0;
int v[2][MAXN+1];
queue <na> q;
inline int gx(int x,int q1,int q2){k=0;for (register int i=m+1;i;i--) k=k*3+(i==x?q1:(i==x+1?q2:a[i]));return k;}
inline void up(int r,int z,int lj){
    if (r==en){
        ans+=lj;
        if (ans>=INF) ans-=INF;
        return;
    }
    r++;
    k=r%2;
    if (v[k][z]!=r) v[k][z]=r,f[k][z]=0,q.push(na(r,z));
    f[k][z]+=lj;if (f[k][z]>=INF) f[k][z]-=INF;
}
char c[101];
int main(){
    register int i,j,p;
    scanf("%d%d",&n,&m);
    if (n<m){
        swap(n,m);
        for (j=1;j<=m;j++){
            scanf("%s",c);
            for (i=1;i<=n;i++)
            map[j][i]=c[i-1]=='_';
        }
    }else{
        for (j=1;j<=n;j++){
            scanf("%s",c);
            for (i=1;i<=m;i++)
            map[i][j]=c[i-1]=='_';
        }
    }
    en=n*m-1;
    while(!map[en%m+1][en/m+1]) en--;
    f[0][0]=v[0][0]=1;
    q.push(na(0,0));
    while(!q.empty()){
        na no=q.front();q.pop();
        int an=f[no.x%2][no.z];
        if(no.x%m==0) no.z*=3;
        x=no.x%m+1;y=no.x/m+1;
        for (i=1;i<=m+1;i++) a[i]=0;
        for (i=1,j=no.z;j;i++,j/=3) a[i]=j%3;
        if (!map[x][y]) up(no.x,gx(100,0,0),an);else
        if (a[x]==1&&a[x+1]==1) up(no.x,gx(x,0,0),an);else
        if (a[x]==0&&a[x+1]==0){
            if (map[x+1][y]) up(no.x,gx(x,0,1),an);
            if (map[x][y+1]) up(no.x,gx(x,1,0),an);
            if (map[x][y+1]&&map[x+1][y]) up(no.x,gx(x,2,2),an);
        }else
        if (a[x]==0){
            if (map[x][y+1]) up(no.x,gx(x,a[x+1],0),an);
            if (map[x+1][y]&&a[x+1]==1) up(no.x,gx(x,0,2),an);
            if (a[x+1]==2) up(no.x,gx(x,0,0),an);
        }else
        if (a[x+1]==0){
            if (map[x+1][y]) up(no.x,gx(x,0,a[x]),an);
            if (map[x][y+1]&&a[x]==1) up(no.x,gx(x,2,0),an);
            if (a[x]==2) up(no.x,gx(x,0,0),an);
        }
    }
    printf("%d\n",ans);
}

 

 
posted @ 2016-01-19 21:36  swm_sxt  阅读(400)  评论(0编辑  收藏  举报