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


    简单的状压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 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

  • 相关阅读:
    Computability 2: Gödel Number
    Computability 1: Computational Models
    Axiomatic Set Theory
    External Sorting Model
    Minimum Spanning Tree
    All-Pairs Shortest Paths
    Python 泰坦尼克生存率预测(修改)
    Python 分析Kaggle_Titanic案例
    Python 北京二手房成交数据分析过程
    数据挖掘主要解决的四类问题以及常用到的算法
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4644097.html
Copyright © 2020-2023  润新知