标签 - 插头DP

插头DP    2016-09-24 19:24:59    328    1    0

Description

 

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

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

Input

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

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

Output

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

Sample Input

2 2

*_

__

Sample Output

1

HINT

R*C<=100

 

Solution

第一次写插头DP...

看的是CDQ的论文.然后自己yy了一下

写了两个晚上+一个下午..整个人都不好了

思路大概就是0表示没有插头,1表示有一个没有拐过弯的插头,2表示有一个拐过弯的插头,具体转移的话可以看代码

用四进制存状态速度较快,在我的代码里,第一位存左插头,2~m+1位存'上插头的队列',这样转移比较方便

注意换行的时候,不要转移包含左插头的状态.

思路非常简单,实现非常鬼畜......

 

#include <bits/stdc++.h>
using namespace std;
const int mo = 20110520;
const int maxm = 11;
const int maxn = 101;
const int maxs = 5e6;

int n, m;
int dp[2][maxs];

int bound = 1;

bool a[maxn][maxn];

inline int change(register int x, register int up, register int left)
{
    x >>= 4;
    x <<= 2;
    return x | left | up * bound;
}


int main()
{
    if (fopen("2331.in", "r") != NULL) {