2331: [SCOI2011]地板

插头dp;
姿态1;

#include<cstdio>
#include<algorithm>
#include<bitset>
#define rep(i,k,n) for(int i=k;i<=(n);i++)
#define mod 20110520
using namespace std;
const int N = 5000000;
int n, m;
int g[N], ans[N], state[700000], op = 0, top = 0;
char s[105][105];
int a[105][105];

bool ok(int x) {
    rep(i, 0, m) {
        if((x >> (i * 2)) % 4 == 3)return false;
    }
    return true;
}
void init_state() {

    rep(i, 0, (1 << ((m+1) * 2)) - 1)if(ok(i))state[++top] = i;  //
}

inline int F(int x, int pos, int up, int left) {
    int tmp = (x >> (pos * 2)) % 4;
    tmp ^= up;
    x ^= (tmp << (pos * 2));
    x >>= 2;
    x <<= 2;
    x ^= left;
    return x;
}

int main() {
 //   freopen("in.in", "r", stdin);
    scanf("%d%d", &n, &m);
    rep(i, 1, n)scanf("%s", s[i] + 1);

    if(n >= m) {
        rep(i, 1, n)rep(j, 1, m)a[i][j] = (s[i][j] == '_' ? 1 : 0);
    } else {
        rep(i, 1, n)rep(j, 1, m)a[j][i] = (s[i][j] == '_' ? 1 : 0);
        swap(n, m);
    }

    init_state();
    ans[0]=1;
    rep(i, 1, n) {
        rep(j, 1, m) {
            rep(k, 1, top)g[state[k]] = 0;

            if(a[i][j]) {

                rep(k, 1, top) {
                    int tmp = state[k];
                    if(!ans[state[k]])continue;
                    int left = tmp % 4;
                    int up = (tmp >> (j * 2)) % 4;

                    if(!left && !up) {
                        int ne = F(tmp, j, 2, 0);
                        g[ne] = (g[ne] + ans[tmp]) % mod;
                        ne = F(tmp, j, 0, 2);
                        g[ne] = (g[ne] + ans[tmp]) % mod;
                        ne = F(tmp, j, 1, 1);
                        g[ne] = (g[ne] + ans[tmp]) % mod; //轮廓线!!
                    }

                    if(left == 1 && up == 0) {
                        int ne = F(tmp, j, 0, 1);
                        g[ne] = (g[ne] + ans[tmp]) % mod;
                        ne = F(tmp, j, 0, 0);
                        g[ne] = (g[ne] + ans[tmp]) % mod;
                    }

                    if(left == 0 && up == 1) {
                        int ne = F(tmp, j, 1, 0);
                        g[ne] = (g[ne] + ans[tmp]) % mod;
                        ne = F(tmp, j, 0, 0);
                        g[ne] = (g[ne] + ans[tmp]) % mod;
                    }
                    if(left== 2 && up == 0) {
                        int ne = F(tmp, j, 0, 2);
                        g[ne] = (g[ne] + ans[tmp]) % mod;
                        ne = F(tmp, j, 1, 0);
                        g[ne] = (g[ne] + ans[tmp]) % mod;
                    }


                if(left == 0 && up == 2) {
                    int ne = F(tmp, j, 2, 0);
                    g[ne] = (g[ne] + ans[tmp]) % mod;
                    ne = F(tmp, j, 0, 1);
                    g[ne] = (g[ne] + ans[tmp]) % mod;
                }

                if(left == 2 && up == 2) {
                    int ne = F(tmp, j, 0, 0);
                    g[ne] = (g[ne] + ans[tmp]) % mod;
            }
        }


        rep(k, 1, top)ans[state[k]] = g[state[k]];
    }

    else {
        rep(k, 1, top) {int tmp = state[k]; if((tmp % 4) || ((tmp >> (j * 2)) % 4))ans[tmp] = 0;
        }
    }

}
rep(k, 1, top) { int tmp = state[k];   if(tmp % 4)ans[tmp] = 0;}
}
printf("%d\n",ans[0]);
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值