您的位置:首页 > 其它

BZOJ 1087: [SCOI2005]互不侵犯King( 状压dp )

2015-07-13 22:15 585 查看


简单的状压dp...

dp( x , h , s ) 表示当前第 x 行 , 用了 h 个 king , 当前行的状态为 s .

考虑转移 : dp( x , h , s ) = ∑ dp( x - 1 , h - cnt_1( s ) , s' ) ( s and s' 两行不冲突 , cnt_1( s ) 表示 s 状态用了多少个 king )

我有各种预处理所以 code 的方程和这有点不一样

----------------------------------------------------------------------------------

#include<cstdio>

#include<cstdlib>#include<cstring>#include<algorithm>#include<vector>#include<iostream> #define clr( x , c ) memset( x , c , sizeof( x ) )#define rep( i , n ) for( int i = 0 ; i < n ; ++i )#define b( i ) ( 1 << ( i ) ) using namespace std; typedef long long ll;const int maxn = 10;const int maxstate = 100; vector< int > state;vector< int > cnt;vector< int > ok[ maxstate ];int n , k;ll d[ maxn ][ maxn * maxn ][ maxstate ]; void init() { state.clear() , cnt.clear(); clr( d , -1 ); clr( d[ 0 ] , 0 ); cin >> n >> k; rep( s , b( n ) ) if( ! ( s & ( s << 1 ) ) ) { state.push_back( s ); int t = 0; for( int h = s ; h ; h >>= 1 ) t += h & 1; cnt.push_back( t ); d[ 0 ][ t ][ state.size() - 1 ] = 1; } rep( i , state.size() ) ok[ i ].clear(); rep( i , state.size() ) for( int j = i ; j < state.size() ; j++ ) if( ! ( state[ j ] & state[ i ] ) && ! ( ( state[ j ] << 1 ) & state[ i ] ) && ! ( ( state[ i ] << 1 ) & state[ j ] ) ) { ok[ i ].push_back( j ); if( i != j ) ok[ j ].push_back( i ); }} ll dp( int x , int h , int t ) { if( h < 0 ) return 0; ll &ans = d[ x ][ h ][ t ]; if( ans != -1 ) return ans; ans = 0; if( h < cnt[ t ] ) return ans; for( vector< int > :: iterator it = ok[ t ].begin() ; it != ok[ t ].end() ; it++ ) ans += dp( x - 1 , h - cnt[ t ] , *it ); return ans;} void work() { ll ans = 0; rep( i , state.size() ) ans += dp( n - 1 , k , i ); cout << ans << "\n";} int main() {// freopen( "test.in" , "r" , stdin );// freopen( "test.out", "w", stdout ); init(); work(); return 0; } ----------------------------------------------------------------------------------

1087: [SCOI2005]互不侵犯King

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1974 Solved: 1171
[Submit][Status][Discuss]

Description

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

Input

只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

Output

方案数。

Sample Input

3 2

Sample Output

16

HINT

Source

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