暑假集训Day2 状压dp 特殊方格棋盘
首先声明 : 这是个很easy的题 可这和我会做有什么关系
题目大意:
在n*n的方格棋盘上放置n个车,某些格子不能放,求使它们不能互相攻击的方案总数。
注意:同一行或同一列只能有一个车,否则会相互攻击、
输入:
输入文件第一行,有两个数n, m ,n表示方格棋盘大小,m表示不能放的格子数量
下面有m行,每行两个整数,为不能放的格子的位置。
算法分析:
1. 显然这是个状压dp(好吧没有那么显然,但是是状压dp就完了) 状态很多而且给出的数据范围很小(这个题给出的20>=n)
2. 我们定义一个数组f[i],表示第 i 个状态所满足的方案数
举个栗子: 1011 就可以表示当前行的状态为第二列还可以放车,而第一三四行已经在之前的状态中放车了(~~一列只能有一个车这不是显然吗~~)
3. 题中给出一个限制 , 即有m个位置是不能放车的 , 我们用a数组存储该位置
**这个地方就要按着状压dp自己的方式存储了**
再举个栗子: 如果第二行第三列有个障碍物 那么我们将a[2] += 1<<(3-1)(这里将a数组初始化为0 想象一下一个二进制串在是0的时候 就是 000000 如果要在第三列的位置加上障碍物 可以想象到就是000100 也就是0 + 1<<(3-1))
4. 在这个地方我们先提及一下lowbit数组 `int lowbit(int x){return x & -x;}`
lowbit数组的目的是求出x的二进制表示中最小位的1的位置
还是举个例子 101000 lowbit的结果就是1000
1100 lowbit的结果就是100
具体实现可参见度娘
lowbit数组具体用处我们已经了解了 那么lowbit数组有什么用呢?
再来回想一下我们定义的f数组 当前i表示状态 如果我们用 for(int i=S;i;i-=lowbit(i))cnt++;这样的代码
很轻松就可以求出当前状态中1的个数 , 也就是当前状态已经放了的车的个数,以及当前为第几行 ,显然个数 = cnt = 第几行(一个n*n的方格,放n个车,每一行有且仅有一个车)
5.然后就可以进行动态转移方程了,具体方程如下
这里的i即枚举的当前行的每一个可能放的车(我们只知道当前行一定会放一个车,但是车在哪里我们并不清楚,因此枚举一遍并累加满足条件的方案书)
而a[cnt]则表示当前行的障碍物情况
刚才我们已经提过lowbit(i)可以求出最右边的i的位置 我们外层的i每次减去一个i 即进行当前行下个车可能位置的求解
注意一个小细节`a[cnt] & lowbit(i)`这里表示当前行障碍物并不与当前行的车位置冲突,可以在这里放车,即可以由上一行的状态转移过来
s = S^lowbit(i) :S 异或 lowbit(i)即求出如果当前行车的位置在lowbit(i)那么上一行的状态就是s 然后累加到当前行的方案数即可
for(int i=S;i;i-=lowbit(i)){
if(!(a[cnt] & lowbit(i))){
int s=S^lowbit(i);
f[S]+=f[s];
}
}
AC代码
#include<bits/stdc++.h>
const int maxn=(1<<20)-1;
typedef long long LL;
LL f[maxn],a[25];
int lowbit(int x){return x & -x;};
int main(){
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int x,y;scanf("%d%d",&x,&y);
a[x]+=1<<(y-1);
}
f[0]=1;
int maxs=1<<n;
for(int S=1;S<=maxs;++S){
int cnt=0;
for(int i=S;i;i-=lowbit(i))cnt++;
for(int i=S;i;i-=lowbit(i)){
if(!(a[cnt] & lowbit(i))){
int s=S^lowbit(i);
f[S]+=f[s];
}
}
}
printf("%lld\n",f[maxs-1]);
return 0;
}
暑假集训Day2 状压dp 特殊方格棋盘的更多相关文章
- poj 3254 Corn Fields (状压dp)(棋盘dp)
状压dp入门题 因为当前行的状态只和上一行有关 所以可以一行一行来做 因为m <= 12所以可以用二进制来表示放了或者没有放 0表示没放,1表示放 f[i][state]表示第i行状态为stat ...
- [状压dp]HDOJ1565 方格取数(1)
中文题~~ 题意略 $n\le 20$ ! 很明显是状压! #include <cstdio> #include <cstdlib> #include <cstring& ...
- POJ 1185 炮兵阵地 (状压dp)(棋盘dp)
这题和poj 3254很像,但是更复杂了一些 都属于棋盘里放东西,然后又各种各样的限制,然后求方案或者最大值 (1)上一道题距离要大于1,这道题是大于2.所以判断的时候变成 !(x & (x ...
- 暑假集训Day2 互不侵犯(状压dp)
这又是个状压dp (大型自闭现场) 题目大意: 在N*N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. ...
- 暑假集训 || 状压DP
emm 位操作实现技巧: 获得第i位的数据: if(!(data & (1<< i))) 则data的第 i 位为0,else 为 1 设置第i位为1,data=(data | ...
- 暑假集训Day 4 P4163 [SCOI2007]排列 (状压dp)
状压dp (看到s的长度不超过10就很容易想到是状压dp了 但是这个题的状态转移方程比较特殊) 题目大意 给一个数字串 s 和正整数 d, 统计 s 有多少种不同的排列能被 d 整除(可以有前导 0) ...
- HDU 1565&1569 方格取数系列(状压DP或者最大流)
方格取数(2) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]
题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...
- 特殊方格棋盘【状压DP】
特殊方格棋盘[状压DP] 讲真状压DP这个东西只不过是有那么亿丢丢考验心态罢了(确信) 先从板子题说起,另加一些基础知识 题目描述 在的方格棋盘上放置n 个车,某些格子不能放,求使它们不能互相攻击的方 ...
随机推荐
- 【极客思考】计算机网络:Wireshark抓包分析TCP中的三次握手与四次挥手
[摘要]本文重点分析计算机网络中TCP协议中的握手和挥手的过程. [前提说明] 前段时间突然看到了一篇关于TCP/IP模型的文章,心想这段时间在家里也用wireshark抓了点包,那么想着想着就觉得需 ...
- Orcle 查询语句
首先,以超级管理员的身份登录oracle sqlplus sys/bjsxt as sysdba --然后,解除对scott用户的锁 alter user scott ac ...
- Rocket - tilelink - Parameters
https://mp.weixin.qq.com/s/1I6DcONr0Mg7xiX8F1C7SQ 简单介绍TileLink相关的参数实现(具体问题暂时不展开,后续用到时再做分析). ...
- JAVASE(十四) 集合: 数组和集合、Collection、Iterator、List、Set、Map
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.数组和集合 1.1 内存中对数据进行存储和管理的“容器”:数组,集合 1.2 数组存储的特点和缺点 ...
- 面试题: SpringBoot 的自启动原理
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 引言 不论在工作中,亦或是求职面试,Spring Boot 已经成为我们必知必会的技能项.除了比较老旧的 ...
- Java实现 LeetCode 508 出现次数最多的子树元素和
508. 出现次数最多的子树元素和 给出二叉树的根,找出出现次数最多的子树元素和.一个结点的子树元素和定义为以该结点为根的二叉树上所有结点的元素之和(包括结点本身).然后求出出现次数最多的子树元素和. ...
- Java实现 LeetCode 377 组合总和 Ⅳ
377. 组合总和 Ⅳ 给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数. 示例: nums = [1, 2, 3] target = 4 所有可能的组合为: (1, 1 ...
- Java实现指定年份月份的日历表
输入指定的年份与月份,看这个月的日历表 package Xueying_Liu; import java.util.Scanner; public class rilibiao { public st ...
- java实现第五届蓝桥杯供水设施
供水设施 X星球的居民点很多.Pear决定修建一个浩大的水利工程,以解决他管辖的N个居民点的供水问题.现在一共有N个水塔,同时也有N个居民点,居民点在北侧从1号到N号自西向东排成一排:水塔在南侧也从1 ...
- Java实现第八届蓝桥杯正则问题
正则问题 考虑一种简单的正则表达式: 只由 x ( ) | 组成的正则表达式. 小明想求出这个正则表达式能接受的最长字符串的长度. 例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是 ...