特殊方格取数
来源:互联网 发布:矩阵半张量积等式的解 编辑:程序博客网 时间:2024/04/30 03:52
特殊方格取数
Description
在n*n(n≤20)的方格棋盘上放置n 个车,某些格子不能放,求使它们不能互相攻击的方案总数。
Input
第一行,有两个数 n 、 m ,n表示方格棋盘大小,m表示不能放的格子数量
下面有m行,每行两个整数,为不能放的格子的位置。
Output
只有一行,即得出的方案总数。
Sample Input
2 1
1 1
Sample Output
1
Source
动态规划, 位运算, 排列组合, 状态压缩 ,容斥原理
Solution
用vis[i]表示第i行的放置情况(记录不能放置的状态),储存一个二进制数,第j为0表示(i, j)没有棋子,为1表示(i, j) 有棋子
对于不能放的地方,直接在二进制的储存中用1表示即可
然后对于每一种状态,先统计出该状态已经放置棋子的个数(用lowbit统计),放置了几个棋子即为第即行(每行只能放置一个棋子),然后统计出该状态与改行不能放置的关系,如果有一位同为1,即该状态不合法,找到合法状态DP更新
Code
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <stack>#include <map>#include <vector>#include <queue>#define L (1 << 20)#define LL long longusing namespace std;int n, m, a, b, cnt;LL vis[30], f[L];inline int lowbit(int x) { return x & (-x);}int main() { freopen("2140.in", "r", stdin); freopen("2140.out", "w", stdout); scanf("%d %d", &n, &m); for (int i = 1; i <= m; ++i) { scanf("%d %d", &a, &b); vis[a] += 1 << (b - 1); } f[0] = 1; for (int i = 1; i < (1 << n); ++i) { cnt = 0; for (int j = i; j > 0; j -= lowbit(j)) cnt++; for (int j = i; j > 0; j -= lowbit(j)) if (!(vis[cnt] & lowbit(j))) f[i] += f[i - lowbit(j)]; } printf("%lld\n", f[(1 << n) - 1]); return 0;}
Summary
在将一种状态与该行不能放置的情况进行比较时,需要注意只要有一位同为1即不合法,所以判断方程应为:
if (!(vis[cnt] & lowbit(j)))
而不是:
if (vis[cnt] != lowbit(j))
因为判断合法错误WA了一次
0 0
- 特殊方格取数
- 方格取数(1)
- 方格取数(2)
- 关于方格取数
- 方格取数
- 方格取数
- 方格取数(1)
- 方格取数(2)
- 方格取数
- 方格取数
- 方格取数
- 方格取数
- 方格取数
- 方格取数
- 方格取数 蓝桥杯
- Noip2000方格取数
- 三次方格取数
- 方格取数
- 一些通过uv纹理坐标实现的简单shader(一)
- 浅尝树莓派3之串口配置
- 使用dwz框架导出当页数据
- 多行游标
- JVM调优总结
- 特殊方格取数
- JS无法取得display:none元素的宽高
- linux命令的理解
- Android简单相机开发
- 常用Oracle语句
- httpRequest
- revit获取当前模型中板的数量
- 外卖-----高并发架构设计方案
- 浙江第四届省赛第一题