SCOI2005 互不侵犯 [状压dp]
题目大意:有n*n个格子,你需要放置k个国王使得它们无法互相攻击,每个国王的攻击范围为上下左走,左上右上左下右下,共8个格子,求最多的方法数
看到题目,是不是一下子就想到了玉米田那道题,如果不会的话可以去我另外一篇博客里面看看,里面有玉米田详细解答方案.
好,回到这道题.首先,看到数据范围,很自然的想到状压dp.题目要求我们已经放了国王格子的上下左右以及左上右上左下右下都不能放国王,那么我们就可以通过上一行的状态来更新这一行的状态,即dp[i][state]表示到第i行状态为state满足条件的个数,但是这样很显然是不够的,因为题目只让我们选k个,所以还要加一维来储存个数,即dp[i][state][j]表示到第i行状态为state已经放置了j个国王的满足条件的个数
dp方程应该很好想吧,和玉米田差不多
dp[i+1][state][j]+=dp[i][state'][k]
现在来分步操作一下
首先是预处理,我们可以把左右两边均无1理解为一个状态没有相邻的1
void init()
{
for(lol i=;i<(<<n);i++)
if(!(i&(i<<)))//如果这个状态没有相邻的1
{
can[++cnt]=i;//保存下来
lol c=;
for(lol j=;j<=n;j++) if(i&(<<(j-))) c++;//统计这个状态有多少个1
sum[cnt]=c;
}
}
然后就是初始化第1行
for(lol i=;i<=cnt;i++)
{
dp[][can[i]][sum[i]]=;
}
dp过程,题目要求左上右上均无1,那么我们可以把上一行的状态分别右移和左移,再相与,若为0则代表这个状态合法,还有就是转移状态的时候,sum[k]不能直接+=sum[j],然后dp[i+1][can[k]][sum[k]]+=dp[i][can[j]][sum[j]]因为要枚举很多次,这样sum[k]一直加下去会爆long long,所以改用for循环枚举
for(lol i=;i<n;i++)//枚举第1~m-1行
for(lol j=;j<=cnt;j++)//枚举第i行的状态
for(lol k=;k<=cnt;k++)//枚举第i+1的状态
if(!(can[j]&can[k]) && !(can[j]<<&can[k]) && !(can[j]>>&can[k]))//如果它对应的这一位以及左右都没有1
for(lol l=;l+sum[k]<=r;l++)//枚举这一个状态可以放多少个1
dp[i+][can[k]][l+sum[k]]+=dp[i][can[j]][l];//转移状态
然后就是统计最后结果了,因为题目要求我们选k个,而且最终的结果都保存在最后一行,所以枚举最后一行的状态就行了
完整版代码,个人感觉还是比较简洁易懂的
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#define in(i) (i=read())
using namespace std;
typedef long long lol;
lol read()
{
lol ans=,f=;
char i=getchar();
while(i<''||i>'')
{
if(i=='-') f=-;
i=getchar();
}
while(i>=''&&i<='')
{
ans=(ans<<)+(ans<<)+i-'';
i=getchar();
}
return ans*f;
}
lol can[],dp[][<<][],sum[];
lol n,r,cnt,tot;
void init()
{
for(lol i=;i<(<<n);i++)
if(!(i&(i<<)))//如果这个状态没有相邻的1
{
can[++cnt]=i;//保存下来
lol c=;
for(lol j=;j<=n;j++) if(i&(<<(j-))) c++;//统计这个状态有多少个1
sum[cnt]=c;
}
}
int main()
{
lol ans=;
in(n);in(r);
init();
for(lol i=;i<=cnt;i++)
dp[][can[i]][sum[i]]=;
for(lol i=;i<n;i++)//枚举第1~m-1行
for(lol j=;j<=cnt;j++)//枚举第i行的状态
for(lol k=;k<=cnt;k++)//枚举第i+1的状态
if(!(can[j]&can[k]) && !(can[j]<<&can[k]) && !(can[j]>>&can[k]))//如果它对应的这一位以及左右都没有1
for(lol l=;l+sum[k]<=r;l++)//枚举这一个状态可以放多少个1
dp[i+][can[k]][l+sum[k]]+=dp[i][can[j]][l];//转移状态
for(lol i=;i<=cnt;i++)
ans+=dp[n][can[i]][r];//最后答案都在最后一行,记得开long long
printf("%lld\n",ans);
return ;
}
SCOI2005 互不侵犯 [状压dp]的更多相关文章
- BZOJ1087[SCOI2005]互不侵犯——状压DP
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入 只有一行,包含两个数N,K ( ...
- P1896 [SCOI2005]互不侵犯 状压dp
正解:状压dp 解题报告: 看到是四川省选的时候我心里慌得一批TT然后看到难度之后放下心来觉得大概没有那么难 事实证明我还是too young too simple了QAQ难到爆炸TT我本来还想刚一道 ...
- [SCOI2005]互不侵犯 (状压$dp$)
题目链接 Solution 状压 \(dp\) . \(f[i][j][k]\) 代表前 \(i\) 列中 , 已经安置 \(j\) 位国王,且最后一位状态为 \(k\) . 然后就可以很轻松的转移了 ...
- luogu1896 [SCOI2005]互不侵犯 状压DP
题目大意 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子.( 1 <=N <=9, 0 ...
- NOI P1896 互不侵犯 状压DP
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 注:数据有加强(2018/4/25) ...
- _bzoj1087 [SCOI2005]互不侵犯King【dp】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1087 令f(i, j, k)表示前i列,二进制状态为j,已经用了k个国王的方案数,则 f(i ...
- 洛谷——P1896 [SCOI2005]互不侵犯
P1896 [SCOI2005]互不侵犯 状压DP入门题 状压DP一般需要与处理状态是否合法,节省时间 设定状态dp[i][j][k]表示第i行第j个状态选择国王数为k的方案数 $dp[i][j][n ...
- 状压DP概念 及例题(洛谷 P1896 互不侵犯)
状压DP 就是状态压缩DP.所谓状态压缩,就是将一些复杂的状态压缩起来,一般来说是压缩为一个二进制数,用01来表示某一元素的状态. 比如一排灯泡(5个) 我们可以用一串二进制01串来表示他们的状态 1 ...
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
随机推荐
- python 装饰器 回顾 及练习
# 复习 # 讲作业 # 装饰器的进阶 # functools.wraps # 带参数的装饰器 # 多个装饰器装饰同一个函数 # 周末的作业 # 文件操作 # 字符串处理 # 输入输出 # 流程控制 ...
- 【Java】关于Spring框架的总结 (三)
前文对 Spring IoC 和 Spring AOP 的实现方法进行了整合.如果有不明白的或有质疑的地方可以评论出来,一起探讨问题,帮助别人也是帮助自己!本文探讨的中心主要放在 Spring 的注解 ...
- 30分钟 带你浅入requirejs源码
因为最近项目想现实一个单页功能,用的是react ,然后看了一下react route,挖槽 gzip后16k? 然后我简单写了一个纯单页(不支持多页的单页,所有入口都经过rewrite跑到index ...
- nodejs的交叉(跨平台)编译(to android)
nodejs的二进制包有两种安装方式node-gyp以及node-pre-gyp 这两条命令会写入该包的安装脚本. node-gyp是使用gyp工具编译源码,因此必须指定交叉编译器(参见http:// ...
- 今天买了个pro,开始ios开发
今天买了个mac pro 开始ios开发啦,爽!
- Python 3 学习笔记之——面向对象
1. 类的介绍 类(Class) 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例,类是对象的抽象. 方法:类中定义的函数. 类变量:类变量在整个实 ...
- LeetCode 237 ——删除链表中的结点
1. 题目 2. 解答 因为给定的只有一个待删除的结点指针,我们并不知道其前面结点,所以需要将待删除结点后面的结点值复制到前面结点去,然后指向其后的第二个结点即可. /** * Definition ...
- DM8168通过GPMC接口与FPGA高速数据通信实现
硬件:TI达芬奇TMS320DM8168(以下简称DSP).EP4CE6E22C8N(以下简称FPGA) 软件:linux-2.6.37 转载请注明出处- http://www.cnblogs.com ...
- BZOJ 2756 SCOI2012 奇怪的游戏 最大流
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2756 Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N ...
- 软工实践 - 第二十七次作业 Beta 冲刺(5/7)
队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10134471.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...