首先声明 : 这是个很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 特殊方格棋盘的更多相关文章

  1. poj 3254 Corn Fields (状压dp)(棋盘dp)

    状压dp入门题 因为当前行的状态只和上一行有关 所以可以一行一行来做 因为m <= 12所以可以用二进制来表示放了或者没有放 0表示没放,1表示放 f[i][state]表示第i行状态为stat ...

  2. [状压dp]HDOJ1565 方格取数(1)

    中文题~~ 题意略 $n\le 20$ ! 很明显是状压! #include <cstdio> #include <cstdlib> #include <cstring& ...

  3. POJ 1185 炮兵阵地 (状压dp)(棋盘dp)

    这题和poj 3254很像,但是更复杂了一些 都属于棋盘里放东西,然后又各种各样的限制,然后求方案或者最大值 (1)上一道题距离要大于1,这道题是大于2.所以判断的时候变成 !(x & (x ...

  4. 暑假集训Day2 互不侵犯(状压dp)

    这又是个状压dp (大型自闭现场) 题目大意: 在N*N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. ...

  5. 暑假集训 || 状压DP

    emm 位操作实现技巧: 获得第i位的数据:  if(!(data & (1<< i)))  则data的第 i 位为0,else 为 1 设置第i位为1,data=(data | ...

  6. 暑假集训Day 4 P4163 [SCOI2007]排列 (状压dp)

    状压dp (看到s的长度不超过10就很容易想到是状压dp了 但是这个题的状态转移方程比较特殊) 题目大意 给一个数字串 s 和正整数 d, 统计 s 有多少种不同的排列能被 d 整除(可以有前导 0) ...

  7. HDU 1565&1569 方格取数系列(状压DP或者最大流)

    方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  8. HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]

    题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...

  9. 特殊方格棋盘【状压DP】

    特殊方格棋盘[状压DP] 讲真状压DP这个东西只不过是有那么亿丢丢考验心态罢了(确信) 先从板子题说起,另加一些基础知识 题目描述 在的方格棋盘上放置n 个车,某些格子不能放,求使它们不能互相攻击的方 ...

随机推荐

  1. 01 . Mysql简介及部署

    Mysql数据库简介 什么是数据? ​ 数据(data)是事实或观察的结果,是对客观事物的逻辑归纳,是用于表示客观事物的未经加工的原始素材,数据是信息的表现形式和载体,可以是符号,文字,数字,语音,图 ...

  2. php实现ajax请求的方法

    php实现ajax请求的方法 Ajax页面:第一,了解底层逻辑,正是平常的1个提交在无刷新的条件下发出请求后完成回应,之后去针对你需要的条件来做动作. <!DOCTYPE html> &l ...

  3. lua string方法拓展

    --[[-- 用指定字符或字符串分割输入字符串,返回包含分割结果的数组 local input = "Hello,World" local res = string.split(i ...

  4. eclipse中的Invalid text string (xxx).

    这个是说明在eclipse中引用HTML的时候,语法出现了不规范的错误 可以到https://www.w3school.com.cn/index.html里面找找对应对象的问题 我之前就是option ...

  5. JavaSE (四)程序流程控制 -- if 、switch、for、while

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 目录 前置: * . 从键盘读取数据: 1.分支结构 1.1 if-else结构 1.2 switch- ...

  6. Java实现 蓝桥杯VIP 算法训练 黑色星期五

    有些西方人比较迷信,如果某个月的13号正好是星期五,他们就会觉得不太吉利,用古人的说法,就是"诸事不宜".请你编写一个程序,统计出在某个特定的年份中,出现了多少次既是13号又是星期 ...

  7. SQL Server账号密码(sa)登录失败 错误原因:233

    (其实以前经常用的时候,都很简单,最近一段时间不用了,再一看发现都忘记的差不多了,还是写一篇博客吧,防止下一次再在这种问题上面浪费时间) 右键此电脑,点击管理 如果没有此电脑打开文件夹 在这里右键也是 ...

  8. Java实现 洛谷 P1217 [USACO1.5]回文质数 Prime Palindromes

    import java.util.Scanner; public class Main { private static Scanner cin; public static void main(St ...

  9. java实现第四届蓝桥杯公式求值

    公式求值 输入n, m, k,输出图1所示的公式的值.其中C_n^m是组合数,表示在n个人的集合中选出m个人组成一个集合的方案数.组合数的计算公式如图2所示. 输入的第一行包含一个整数n:第二行包含一 ...

  10. java实现第四届蓝桥杯剪格子

    剪格子 题目描述 如图p1.jpg所示,3 x 3 的格子中填写了一些整数. 我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60. 本题的要求就是请你编程判定:对给定的m x n 的格子 ...