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

1087: [SCOI2005]互不侵犯King



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

分析:


老套路,预先处理出一行内合法方案,减少枚举数。

定义状态f[i][j][k]第i行,状态为j,目前一共放了k个国王,转移走就行了。

AC代码:


# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
const int N = 1 << 9;
int cnt,state[102],num[102],P,n,c;
long long f[10][102][102];
int lowbit(int r){
    return r & -r;
}
void work(){
    for(int i = 0;i < P;i++){
        int pre = lowbit(i),r = i - pre;bool flag = true;
        while(r){
            if(lowbit(r) / pre <= 2){
                flag = false;break;
            }
            pre = lowbit(r);r -= pre;
        }
        if(flag)state[++cnt] = i;
    }
    for(int i = 1;i <= cnt;i++){
        int r = state[i];
        while(r){
            r -= lowbit(r);
            num[i]++;
        }
    }
}
int main(){
    scanf("%d %d",&n,&c);P = 1 << n;
    work();
    f[0][1][0] = 1LL;
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= cnt;j++){
            for(int k = 1;k <= cnt;k++){
                for(int l = 0;l <= c;l++){
                if(state[j] & state[k])continue;
                if((state[j] >> 1) & state[k])continue;
                if((state[j] << 1) & state[k])continue;
                f[i][j][l + num[j]] += f[i - 1][k][l];
              }
            }
        }
    }
    long long ans = 0;
    for(int i = 1;i <= cnt;i++){
      ans += f[n][i][c];
    }
    printf("%lld\n",ans);
}
时间: 2024-11-05 14:48:53

[Bzoj1083][SCOI2005]互不侵犯king(状压dp)的相关文章

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

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

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 Solution 状压$dp$就是把状态压缩成二进制数,利用二进制的位运算改进算法的一种方法

【BZOJ1087】 [SCOI2005]互不侵犯King 状压DP

经典状压DP. f[i][j][k]=sum(f[i-1][j-cnt[k]][k]); cnt[i]放置情况为i时的国王数量 前I行放置情况为k时国王数量为J 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 #define N 1<<9 5 long long ans; 6 int n,m; 7 int ok_1[N],cnt[N]; 8 int ok_2[N][N]; 9 long

bzoj1087 互不侵犯King 状压dp+bitset

题目传送门 题目大意:中文题面. 思路:又是格子,n又只有9,所以肯定是状压dp,很明显上面一行的摆放位置会影响下一行,所以先预处理出怎样的二进制摆放法可以放在上下相邻的两行,这里推荐使用bitset,否则会比较麻烦.然后dp的数组是f[ i ][ x ][ j ],表示第i行已经放置了x个国王,第 i 行的状态是 j .同时预处理出对于每一种二进制位,可以增加几个国王,计做cnt[ j ],所以得到 if(mp[ s ][ j ]) f[ i +1 ][x +cnt[ j ]][ j ]+=f

【题解】[SCOI2005] 互不侵犯 (状压DP)

[SCOI2005] 互不侵犯 终于懂一点状压DP了… 用一个数的二进制形式表示一整行的状态,比如 18(1010)表示第一列和第三列有国王. 然后用&判断是否可行: if((x&y)||((x<<1)&y)||(x&(y<<1))) continue;1code: #include<iostream>#include<cstdio>#include<cstring>#include<algorithm>

BZOJ 1087 SCOI 2005 互不侵犯King 状压DP

题目大意:一个国王可以攻击到旁边8个位置的格子,现在给出一个N*N的方格,向其中放k个国王,问有多少中摆放方法. 思路:状压DP,f[i][j][k],其中i是行数,j是状态,k是已经取了多少国王.然后暴力枚举状态,看相邻两行之间有没有冲突,若没有冲突,那么就转移. 注意要开long long CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm>

[SCOI2005]互不侵犯(状压Dp)

题目 原题 Solution 看到数据范围就可以想到状压,然后你就可以直接转移就好了? #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<iostream> #include<queue> #include<algorithm> #define ll long long #define file(a) freo

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枚举范围错

[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 <=