BZOJ2331: [SCOI2011]地板

来源:互联网 发布:tomcat启动获取端口号 编辑:程序博客网 时间:2024/04/20 19:44

Description

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

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

Input

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

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

Output

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

Sample Input

2 2

*_

__

Sample Output

1

HINT

R*C<=100

Source

插头DP
反正这种题根本不用思考,只是码农
一直搞不懂网上的题解为什么写法特别清奇
推荐一种写法 最后一位存右插头,1-m位存下插头, 特别好转移,不用考虑左移右移
写Hash的当我没说(这种题为啥要Hash啊不是暴力能随便过吗)
注意开滚动数组优化,我脑抽,强行交了一发700+M的代码
我还脑抽把最后写成了n+m&1纯属脑残
#include <bits/stdc++.h>using namespace std;const int MAXN = 101;const int MAXV = 177147;const int mod = 20110520;char ch[MAXN];int n, m, mp[MAXN][MAXN], dp[2][MAXV], table[MAXN], cur;inline void upd(int &x, int y) { x += y; if( x >= mod ) x -= mod; }inline void solve(){dp[ 0 ][ 0 ] = cur = 1;for( int i = 1 ; i <= n ; i++ )for( int j = 1 ; j <= m ; j++, cur ^= 1 ){memset( dp[ cur ], 0, sizeof dp[ cur ] );for( int k = 0 ; k < table[ m + 1 ] ; k++ ) if( dp[ cur ^ 1 ][ k ] ){int left = k % 3, up = k / table[ j ] % 3 ;if( mp[ i ][ j ] ){if( !left && !up ) upd( dp[ cur ][ k ], dp[ cur ^ 1 ][ k ] );continue; }if( j == 1 && left ) continue;if( !left ){if( !up )upd( dp[ cur ][ k + 2 + table[ j ] * 2 ], dp[ cur ^ 1 ][ k ] ),upd( dp[ cur ][ k + table[ j ] ], dp[ cur ^ 1 ][ k ] ),upd( dp[ cur ][ k + 1 ], dp[ cur ^ 1 ][ k ] );else if( up == 1 )upd( dp[ cur ][ k ], dp[ cur ^ 1 ][ k ] ),upd( dp[ cur ][ k - table[ j ] + 2 ], dp[ cur ^ 1 ][ k ] );elseupd( dp[ cur ][ k ], dp[ cur ^ 1 ][ k ] ),upd( dp[ cur ][ k - table[ j ] * 2 ], dp[ cur ^ 1 ][ k ] );}else if( left == 1 ){if( !up )upd( dp[ cur ][ k ], dp[ cur ^ 1 ][ k ] ),upd( dp[ cur ][ k + table[ j ] * 2 - 1 ], dp[ cur ^ 1 ][ k ] );else if( up == 1 )upd( dp[ cur ][ k - 1 - table[ j ] ], dp[ cur ^ 1 ][ k ] );}else{if( !up )upd( dp[ cur ][ k ], dp[ cur ^ 1 ][ k ] ),upd( dp[ cur ][ k - 2 ], dp[ cur ^ 1 ][ k ] );}}}}int main(){table[ 0 ] = 1; for( int i = 1 ; i <= 11 ; i++ ) table[ i ] = table[ i - 1 ] * 3;scanf( "%d%d", &n, &m );for( int i = 1 ; i <= n ; i++ ){scanf( "%s", ch + 1 );for( int j = 1 ; j <= m ; j++ )if( n < m ) mp[ j ][ i ] = ch[ j ] == '*';else mp[ i ][ j ] = ch[ j ] == '*';}if( n < m ) swap( n, m );solve();return printf( "%d\n", dp[ n * m & 1 ][ 0 ] ), 0;}


0 0