您的位置:首页 > 其它

BZOJ 1725 [Usaco2006 Nov]Corn Fields牧场的安排 状态压缩DP

2017-09-20 15:28 316 查看

大家都很强, 可与之共勉 。

[Usaco2006 Nov]Corn Fields牧场的安排

Description

Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地。FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用。遗憾的是,有些土地相当的贫瘠,不能用来放牧。并且,奶牛们喜欢独占一块草地的感觉,于是FJ不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。当然,FJ还没有决定在哪些土地上种草。 作为一个好奇的农场主,FJ想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择。当然,把新的牧场荒废,不在任何土地上种草,也算一种方案。请你帮FJ算一下这个总方案数。

Input

第1行: 两个正整数M和N,用空格隔开

第2..M+1行: 每行包含N个用空格隔开的整数,描述了每块土地的状态。输入的第i+1行描述了第i行的土地。所有整数均为0或1,是1的话,表示这块土地足够肥沃,0则表示这块地上不适合种草

Output

第1行: 输出一个整数,即牧场分配总方案数除以100,000,000的余数

Sample Input

2 3

1 1 1

0 1 0

Sample Output

9

题意

在一个M*N的矩阵上放草,有些位置不能放置,放的草不能四连通,求方案数。

题解

先处理出补集,用二进制来存, 判断状态合法就是&补集==0

然后就是裸的DP

觉得网上其他的做法好弱233333

# include <bits/stdc++.h>

const int Mod = 100000000 ;

int s [15] ;
int dp [15] [1 << 15 | 1] ;

int main ( )  {
int n, m ;
scanf ( "%d%d", & n, & m ) ;
for ( int i = 1 ; i <= n ; ++ i )
for ( int j = 1 ; j <= m ; ++ j )  {
int c ;
while ( ( c = getchar ( ) ) == ' ' || c == '\n' ) ;
if ( c == '0' ) s [i] |= 1 << j >> 1 ; // complementary set ;
}
int lim = ( 1 << m ) ;
dp [0] [0] = 1 ;
for ( int i = 1 ; i <= n ; ++ i )  {
for ( int j = 0 ; j < lim ; ++ j )  // cur
if ( ! ( j & ( j << 1 ) ) && ! ( j & s [i] ) )  {
for ( int k = 0 ; k < lim ; ++ k )  {  // last
if ( ! ( k & ( k << 1 ) ) && ! ( k & j ) && ! ( k & s [i - 1] ) )  {
dp [i] [j]  += dp [i - 1] [k] ;
if ( dp [i] [j] >= Mod )    dp [i] [j] -= Mod ;
}
}
}
}
int ans ( 0 ) ;
for ( int i = 0 ; i < lim ; ++ i )  {
ans += dp
[i] ;  // if illegal, dp
[i] = 0, so just add directly ;
if ( ans >= Mod )   ans -= Mod ;
}
printf ( "%d\n", ans ) ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: