您的位置:首页 > 其它

[状态压缩DP] POJ 3254

2017-11-16 21:40 281 查看
POJ 3254. Corn Fields 状态压缩DP (入门级)

题目大意是有M×N的玉米地,但其中有些是不肥沃的,不能种植。用1来代表肥沃,0代表不肥沃。另外奶牛不喜欢挨着吃,也就是说要间隔着种植,求有几种种植方式,并将计算结果对1E8取模。

dp[r][j]表示当第r行的种植状态为第j种状态时,现在玉米地的种植方案数。

r是当前行,i、j是状态

状态转移方程: dp[r][j] = dp[r-1][i] + dp[r][j]

不能挨着种:

判断( state[ k ] & state[ j ] ) == 0

这个没有在输入数组的时候取反

虽然取反后判断方便,但我觉得没取反的比较直观

#include <cstdio>
#include <cstring>
#include <iostream>

#define MOD 100000000

int row[ 13 ], state[ 377 ];
int dp[ 13 ][ 377 ];

int main () {

//把有相邻1的不合格状态去掉
int total = 1 << 12;
int validState = 0;
for ( int i = 0; i < total; ++i )
if ( !( i & ( i << 1 ) ) )
state[ validState++ ] = i;
state[ validState ] = total;

int M, N, t;
scanf ( "%d%d", &M, &N );

for ( int i = 0; i < M; ++i )
for ( int j = 0; j < N; ++j ) {
scanf ( "%d", &t );
row[ i ] = ( row[ i ] << 1 ) | t; //没取反
}

total = 1 << N;
for ( int i = 0; i < validState; ++i )
if ( ( row[ 0 ] & state[ i ] ) == state[ i ] ) //第一行state i 可行
dp[ 0 ][ i ] = 1;

for ( int i = 1; i < M; ++i )
for ( int j = 0; j < validState; ++j ) {
if ( ( row[ i ] & state[ j ] ) != state[ j ] )
continue;

for ( int k = 0; k < validState; ++k )
// 存在路径,没有相邻的点
if ( dp[ i - 1 ][ k ] && ( state[ k ] & state[ j ] ) == 0 )
dp[ i ][ j ] = ( dp[ i ][ j ] + dp[ i - 1 ][ k ] ) % MOD;
}

int ans = 0;
for ( int j = 0; j < validState; ++j )
if ( dp[ M - 1 ][ j ] )
ans = ( ans + dp[ M - 1 ][ j ] ) % MOD;

printf ( "%d\n", ans );

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: