標籤:
簡單的狀壓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]互不侵犯KingTime 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 Input3 2Sample Output16HINT
Source
BZOJ 1087: [SCOI2005]互不侵犯King( 狀壓dp )