BZOJ 1087: [SCOI2005]互不侵犯King( 状压dp )
2015-07-13 22:15
585 查看
![](http://images0.cnblogs.com/blog2015/723896/201507/132208295484830.png)
简单的状压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 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 2Sample Output
16HINT
Source
相关文章推荐
- 黑马程序员-学习日记(反射)
- 【C++】深度探索C++对象模型读书笔记--关于对象(Object Lessons)
- 程序语言理解
- SpringMVC 4.1.6 @RestController实例入门
- UVALive 6832 Bit String Reordering
- 编程与创造
- css实现table锁定表头
- linux下压缩工具总结与使用(参考私房菜)
- Android中ImageButton边框完全填充
- 字符串移位包含问题
- HDU 2476 String painter (区间DP)
- UVALive 6959 签到(水题)
- iOS之NSAttributedString-------字符属性
- 黑马程序员—IO(二)File类、Properties类、打印流、序列流(合并流)
- log4j对象改变日志级别
- 黑马程序员——基础学习(九)String的实际案例及StringBuffer/StringBuilder
- 黑马程序员—IO(一)流概述、字符流、字节流、流操作规律
- 黑马程序员-学习日记(多线程安全问题和死锁认识)
- 面向对象五大原则_5.迪米特原则
- NS3网络仿真(6): 总线型网络