1087: [SCOI2005]互不侵犯King

1087: [SCOI2005]互不侵犯King

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 4276  Solved: 2471
[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

/*
* @Author: LyuC
* @Date: 2017-09-03 21:24:43
* @Last Modified by: LyuC
* @Last Modified time: 2017-09-04 21:55:56
*/ /*
题意:在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。 思路:类似八皇后问题,k>n的情况方案数为0,然后剩下的搜索解决 错误:这个和八皇后问题不一样,king只能攻击相邻一格,状压DP dp[i][j][k]表示第i行,j状态,已经按放k个棋子的状态 状态转移:dp[i][j][cnt=从j状态中的棋子数枚举到需要放的总的棋子数]+=
dp[i-1][上一行能满足下一行是j状态的状态][cnt-j状态的棋子数] 总的来说动态规划就是抽象出来状态,就很简单了
*/
#include <bits/stdc++.h> #define MAXN 15
#define MAXT 1024
#define MAXK 105
#define LL long long using namespace std; LL n,k;
LL dp[MAXN][MAXT][MAXK];//dp[i][j][k]表示第i行,第j种状态时,已经放下了k个棋子的方案数
LL tol;
LL cnt;
LL res; bool ok(LL x,LL y){//判断上行的状态是否满足条件
for(LL i=;i<n;i++){
if( (x&(<<i)) == ) continue; if(i==){
if( ( y&( <<i ) ) != || ( y&( <<(i+) ) ) !=)
return false;
}else if(i==n-){
if( ( y&( <<i ) ) != || ( y&( <<(i-) ) ) !=)
return false;
}else{
if( ( y&( <<(i-) ) ) != || ( y&( <<(i+) ) ) != || ( y&( <<i ) ) !=)
return false;
}
}
return true;
} LL judge(LL x){//判断这个状态是不是合格的
LL cur=;
for(LL i=;i<n;i++){
if( ( x&(<<i) ) !=){
if(i==){
if( ( x&( << (i+) ) )!=){
return -;
}
}else if(i==n-){
if( ( x&(<<(i+)) )!= || ( x&(<<(i-)) )!= ){
return -;
}
}else{
if( ( x&(<<(i-)) )!=){
return -;
}
}
cur++;
}
}
return cur;
} inline void init(){
memset(dp,,sizeof dp);
res=;
} int main(){
// freopen("in.txt","r",stdin);
init();
scanf("%lld%lld",&n,&k); tol=(<<n); for(LL i=;i<tol;i++){//初始化状态
cnt=judge(i);
if(cnt!=-){
dp[][i][cnt]=;
}
} for(LL i=;i<n;i++){//从第二行开始递推状态
for(LL j=;j<tol;j++){//枚举当前行的状态
cnt=judge(j);
if(cnt==-) continue;
for(LL l=;l<tol;l++){//枚举上一行的状态
if(ok(j,l)==false) continue;
for(LL d=cnt;d<=k;d++){
dp[i][j][d]+=dp[i-][l][d-cnt];
}
}
}
} for(LL i=;i<tol;i++){
res+=dp[n-][i][k];
}
printf("%lld\n",res);
return ;
}
上一篇:Ubuntu16.04编译安装Redis Desktop Manager


下一篇:hibernate(九) 二级缓存和事务级别详讲