简单的状压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 << "
";
}
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 MBSubmit: 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