【BZOJ 1087】[SCOI2005]互不侵犯King

Description

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

Input

只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

Output

方案数。

Sample Input

3 2

Sample Output

16

同学很早之前打表过了,orz

这题正解状压DP,f[i][s][k]表示第i行上一行的状态为S,选了k个

预处理出所有可行状态DP就好了

 1 #include<cstdio>
 2 #include<cstring>
 3 #define ll long long
 4 using namespace std;
 5 int gs[520],a[520][11];
 6 bool pd[520];
 7 int n,K;
 8 ll ans,f[11][520][90];
 9 bool ok(int x,int y){
10     for(int i=1;i<=9;i++) if(a[x][i]&&(a[y][i]||a[y][i-1]||a[y][i+1])) return 0;
11     return 1;
12 }
13
14 int main(){
15     scanf("%d%d",&n,&K);
16     memset(pd,1,sizeof(pd));
17     for(int i=1;i<=(1<<n)-1;i++){
18         int tmp=i,cnt=0;
19         while(tmp){
20             a[i][++cnt]=tmp&1;gs[i]+=1&tmp;
21             tmp>>=1;
22         }
23         for(int j=1;j<=n;j++) if(a[i][j]==1&&a[i][j+1]==1){
24             pd[i]=0;break;
25         }
26         if(pd[i]) f[1][i][gs[i]]+=1;
27     }
28     f[1][0][0]=1;
29     for(int i=2;i<=n;i++)
30         for(int j=0;j<=(1<<n)-1;j++){
31             if(!pd[j]) continue;
32             for(int k=0;k<=(1<<n)-1;k++){
33                 if(ok(j,k)){
34                     for(int l=gs[k];l<=K;l++)
35                     f[i][k][l]+=f[i-1][j][l-gs[k]];
36                 }
37             }
38         }
39     for(int i=0;i<=(1<<n)-1;i++)if (pd[i]) ans+=f[n][i][K];
40     printf("%lld",ans);
41 } 
时间: 2024-11-05 14:53:26

【BZOJ 1087】[SCOI2005]互不侵犯King的相关文章

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 的方程和这有点不一样 ------------------------------------------------

BZOJ 1087 [SCOI2005]互不侵犯King

水状压 预处理可以用的每行的状态,转移的时候判断上下行是否冲突.记得当时刚学的时候听学长讲感觉这题好难呀. 然后智障的第一次空间开小了第二次忘了开LL,RE了一发又WA了一发... #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<queue> #include<vector>

【BZOJ】1087: [SCOI2005]互不侵犯King

[算法]状态压缩型DP [题解]http://www.cnblogs.com/xtx1999/p/4620227.html (orz) #include<cstdio> #include<algorithm> using namespace std; const int maxn=10,e2=530; long long f[maxn][e2][maxn*maxn]; int n,mk,num[e2],king[e2],ok[e2][e2]; bool selfcheck(int

[SCOI2005]互不侵犯King

1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4255  Solved: 2458 [Submit][Status][Discuss] Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上 左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <=

SCOI2005互不侵犯King

1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1499  Solved: 872[Submit][Status] Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N

[Bzoj1083][SCOI2005]互不侵犯king(状压dp)

1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4595  Solved: 2664[Submit][Status][Discuss] Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K &

BZOJ1087:[SCOI2005]互不侵犯King(状压DP)

[SCOI2005]互不侵犯King Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N) Output 方案数. Sample Input 3 2 Sample Output 16 分析: 经典的状压DP题目,可我竟然调了很长时间都没对,后来发现是DP枚举范围错

[bzoj1087] [SCOI2005]互不侵犯King

http://www.lydsy.com/JudgeOnline/problem.php?id=1087 一个n*n的棋盘,要在上面放国王,每个国王占领周围3*3的土地,求放置K个国王的方案数量. 一开始感觉结论题就打了个表,打一个8的表只要一两分钟??,虽然说n<=9,但是9的估计要很久...说不定考试那几个小时都打不完. 说说正解吧. 考虑壮压dp,如果按照一个个位置dp需要记录轮廓线以及左上角那个位置的情况,但是显然我们不需要那么复杂. 情况数2^9=512   预先处理好  每种情况是否

_bzoj1087 [SCOI2005]互不侵犯King【dp】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1087 令f(i, j, k)表示前i列,二进制状态为j,已经用了k个国王的方案数,则 f(i, j, k) = sigma(i - 1, p, k - num[j]),其中可以从p状态转化到j状态,num[j]表示j状态下的国王数. 乍一看可能会超时,因为共有n * 2^n * n^2个状态,即状态数为O(n^3 * 2^n),转移的复杂度为O(2^n),因此总时间复杂度为O(n^3 *