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

[SCOI2005] 互不侵犯

终于懂一点状压DP了…

用一个数的二进制形式表示一整行的状态,
比如 18(1010)表示第一列和第三列有国王。

然后用&判断是否可行:

if((x&y)||((x<<1)&y)||(x&(y<<1))) continue;
1
code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define FOR(i,n,m) for(register int i=n;i<=m;++i)
using namespace std;

int n,m,tot;
ll ans;
int can[1<<10],num[1<<10];
ll dp[10][1<<10][110];//dp[i][j][k]表示第i行,状态为j,前面摆了k个国王时 的方案数

int sum(int x)//这一种状态有多少个国王(一行)
{
while(x) num[tot]+=(x&1),x>>=1;
return num[tot];
}

int main()
{
scanf("%d%d",&n,&m);
int Max=(1<<n)-1;
FOR(i,0,Max) if(!(i&(i<<1))) can[++tot]=i,dp[1][tot][sum(i)]=1;
FOR(i,2,n)
{
FOR(j,1,tot) FOR(k,1,tot)
{
int x=can[j],y=can[k];
if((x&y)||((x<<1)&y)||(x&(y<<1))) continue;//判断是否可行
FOR(l,0,m) dp[i][j][num[j]+l]+=dp[i-1][k][l];
}
}
FOR(i,1,tot) ans+=dp[n][i][m];
printf("%lld",ans);
return 0;
}
---------------------
作者:#shadow#
来源:CSDN
原文:https://blog.csdn.net/weixin_44663556/article/details/88378924
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/shadow233/p/10660478.html

时间: 2024-11-08 17:41:50

【题解】[SCOI2005] 互不侵犯 (状压DP)的相关文章

1896 [SCOI2005]互不侵犯 状压dp

传送门 这是一道状压dp的经典例题 题目让输出所有可能的方案数 很显然 这是一道动态规划了 由于国王放置的位置有一定的限制 所以我们要在状态转移的过程中增加一维来存储状态 我们这一道题假设f[i][j][k] 意思是在前i行一共放置了j个国王 第i行国王放置的状态是k  存储的值是方案数 首先 我们可以先预处理出左右合法的每行的状态...(有点绕 就是说针对单独的一行 会有那些合法的状态 使得相邻的两个格子最多只能放置一个国王 没有相邻的国王 然后我们开始dp 我们分别枚举i k s i是当前枚

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

【题解】P3959 宝藏 - 状压dp / dfs剪枝

P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m  条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多. 小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某 个宝藏屋的通道,通往哪个宝藏屋则由小明来决定. 在此基础上,小明还需要考虑如何开凿

HDU 5434 Peace small elephant 状压dp+矩阵快速幂

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: 108 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 小明很喜欢国际象棋,尤其喜欢国际象棋里面的大象(只要无阻挡能够斜着走任意格),但是他觉得国际象棋里的大象太凶残了,于是他

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

[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