1896 [SCOI2005]互不侵犯 状压dp

传送门

这是一道状压dp的经典例题

题目让输出所有可能的方案数

很显然 这是一道动态规划了

由于国王放置的位置有一定的限制 所以我们要在状态转移的过程中增加一维来存储状态

我们这一道题假设f[i][j][k] 意思是在前i行一共放置了j个国王 第i行国王放置的状态是k  存储的值是方案数

首先 我们可以先预处理出左右合法的每行的状态。。。(有点绕

就是说针对单独的一行 会有那些合法的状态 使得相邻的两个格子最多只能放置一个国王 没有相邻的国王

然后我们开始dp

我们分别枚举i k s

i是当前枚举到第几行

k是第i行的状态 编号

s是第i-1行的状态编号

然后我们还要判断一下

上下不能相等,对角线不能相等

这些条件都满足之后 我们就可以枚举第i行国王的个数 并从上一行的状态累加到当前状态

最后我们把最后一行 放满ss个国王 的不同状态的f数组的值累加起来就是总的方案数

进行位运算的时候还要注意一点

就是 一定要多加括号!!!

//P1896 [SCOI2005]互不侵犯
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int p[300];
int num[300];//记录每一种状态有多少个1
ll f[10][90][300];
int main()
{
    int n,ss;
    scanf("%d%d",&n,&ss);
    int cnt=0;//合法状态数量
    for(int i=0;i<(1<<n);i++)//枚举合法的n位二进制数
    {
        if((i&(i>>1))==0)//没有左右相邻的国王
        {
            p[++cnt]=i;
            int sta=i;
            while(sta)
            {
                if(sta&1) num[cnt]++;
                sta>>=1;
            }
        }
    }
    f[0][0][1]=1;//什么都不放的方案数是1  初始化
    for(int i=1;i<=n;i++)
        for(int k=1;k<=cnt;k++)
            for(int s=1;s<=cnt;s++)
                if((p[k]&p[s])==0)//没有上下攻击
                    if(((p[k]>>1)&p[s])==0)
                        if(((p[s]>>1)&p[k])==0)
                        {
                            for(int j=num[k]+num[s];j<=ss;j++)
                                f[i][j][k]+=f[i-1][j-num[k]][s];

                        }
    long long ans=0;
    for(int i=1;i<=cnt;i++)
        ans+=f[n][ss][i];
    cout<<ans<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/akioi/p/12219125.html

时间: 2024-10-09 09:53:06

1896 [SCOI2005]互不侵犯 状压dp的相关文章

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

题目链接 Solution 状压 \(dp\) . \(f[i][j][k]\) 代表前 \(i\) 列中 , 已经安置 \(j\) 位国王,且最后一位状态为 \(k\) . 然后就可以很轻松的转移了... 记忆化搜索还是不够啊... 只能会正向 \(dp\) . Code #include<bits/stdc++.h> #define ll long long using namespace std; ll f[10][101][1100],n,K; ll js[1100],sum,ans;

_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 *

SGU 223 little kings BSOJ2772 状压DP

1896 [SCOI2005]互不侵犯King [问题描述]在n*n(1<=n<=10)的棋盘上放k(0<=k<=n*n)个国王(可攻击相邻的8 个格子),求使它们无法互相攻击的方案总数. [输入格式]输入有多组方案,每组数据只有一行为两个整数n和k. [输出格式]每组数据一行为方案总数,若不能够放置则输出0. [问题分析] 由问题很容易联想起经典的“八皇后”问题,似乎就是“皇后”变成了“国王”,而且格子范围似乎也差不多,所求问题也一样.那么这个问题也能用搜索解决吗? 可稍加分析可

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)

[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] 互不侵犯 (状压DP)

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

[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

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 好像若干月前非常Naive地去写过DFS... 然后其实作为状压DP是一道非常好的题啦>< 感觉直接无脑搞时间是下不来的 做了好几道预处理 使得最后DP的过程中没有任何一条转移是无用的 1 program bzoj1087; 2 var i,x,n,k,j,p,q,t1,t2:longint; 3 ans:int64; 4 a:array[-1

[状压DP]SCOI2005 互不侵犯King

题目梗概 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 思考 对于每一行的放置来说 只要不相邻就是正确的摆放放置,其次就是只考虑上一行对这一行的摆放影响就可以了. 实现并不难,用到了很多位运算的知识. 算是一道非常不错的状压dp入门题目. dp[i][j][t] 表示前i个位置状态为j放置了t个 #include <cstdio> #include <algorithm> #i