bzoj2669[cqoi2012]局部极小值 容斥+状压dp
2669: [cqoi2012]局部极小值
Time Limit: 3 Sec Memory Limit: 128 MB
Submit: 774 Solved: 411
[Submit][Status][Discuss]
Description
有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次。如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值。
给出所有局部极小值的位置,你的任务是判断有多少个可能的矩阵。
Input
输入第一行包含两个整数n和m(1<=n<=4, 1<=m<=7),即行数和列数。以下n行每行m个字符,其中“X”表示局部极小值,“.”表示非局部极小值。
Output
输出仅一行,为可能的矩阵总数除以12345678的余数。
Sample Input
3 2
X.
..
.X
Sample Output
60
容斥,推一推可以得到X的个数不超过8个(虽然我不知道是怎么推的)
枚举,从小到大填数,状压dp可以计算出对于此种图的填数方案
用cnt[s]表示状态s下可以填数的方案(包括之前已经填过的X但不包括没填的X)
f[i][s]转移就得到啦(水一波)
这样我们可以保证X的位置一定是周围最小的,但却不能保证其他位置不会出现多余的'X'
于是我们dfs出每一个可以为X的地方,容斥一下就好啦
推荐blog
http://blog.csdn.net/popoqqq/article/details/48028773
取模有毒
a+=b;if(a>=mod)a-=mod;
如果b是负数的话..就炸了!!
调了1h..
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define mod 12345678
#define ll long long
using namespace std;
int n,m,tp,cnt[<<],ok[][];
int dx[]={,,,-,,-,,-,};
int dy[]={,-,,,,-,-,,};
char mp[][];ll ans,f[][<<];
struct node{int x,y;}p[];
int dp(){
memset(cnt,,sizeof(cnt));
memset(f,,sizeof(f));tp=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(mp[i][j]=='X')
p[++tp]=(node){i,j};
for(int st=;st<(<<tp);st++){
memset(ok,,sizeof(ok));
for(int j=;j<=tp;j++)
if(!(st&(<<(j-))))ok[p[j].x][p[j].y]=;
for(int i=;i<=n;i++)
for(int k,j=;j<=m;j++){
for(k=;k<;k++)
if(ok[i+dx[k]][j+dy[k]])break;
if(k==)cnt[st]++;
}
}
f[][]=;
for(int i=;i<=n*m;i++)
for(int st=;st<(<<tp);st++){
(f[i][st]+=f[i-][st]*max(,cnt[st]-i+))%=mod;
for(int k=;k<=tp;k++)
if((<<(k-))&st)(f[i][st]+=f[i-][st^(<<(k-))])%=mod;
}
return f[n*m][(<<tp)-];
}
void dfs(int x,int y,int c){
int t;
if(x==n+){
(ans+=dp()*(c&?-:))%=mod;
return;
}
if(y==m)dfs(x+,,c);
else dfs(x,y+,c);
for(t=;t<;t++)if(mp[dx[t]+x][dy[t]+y]=='X')break;
if(t<)return;
mp[x][y]='X';
if(y==m)dfs(x+,,c+);
else dfs(x,y+,c+);
mp[x][y]='.';
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%s",mp[i]+);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(mp[i][j]=='X')
for(int k=;k<;k++){
int nx=i+dx[k],ny=j+dy[k];
if(mp[nx][ny]=='X'){puts("");return ;}
}
dfs(,,);
ans<?ans+=mod:;
cout<<ans;
return ;
}
bzoj2669[cqoi2012]局部极小值 容斥+状压dp的更多相关文章
- P3160 [CQOI2012]局部极小值 题解(状压DP+容斥)
题目链接 P3160 [CQOI2012]局部极小值 双倍经验,双倍快乐 解题思路 存下来每个坑(极小值点)的位置,以这个序号进行状态压缩. 显然,\(4*7\)的数据范围让极小值点在8个以内(以下示 ...
- [BZOJ2669][CQOI2012]局部最小值(容斥+状压DP)
发现最多有8个限制位置,可以以此为基础DP和容斥. $f_{i,j}=f_{i-1,j}\times (cnt_j-i+1)+\sum_{k\subset j} f_{i-1,k}$ $cnt_j$表 ...
- ARC 093 F Dark Horse 容斥 状压dp 组合计数
LINK:Dark Horse 首先考虑1所在位置. 假设1所在位置在1号点 对于此时剩下的其他点的方案来说. 把1移到另外一个点 对于刚才的所有方案来说 相对位置不变是另外的方案. 可以得到 1在任 ...
- bzoj3812 主旋律 容斥+状压 DP
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3812 题解 考虑对于图的联通性的 DP 的一般套路:总方案 - 不连通的方案. 那么我们只需要 ...
- Comet OJ - Contest #7 C 临时翻出来的题(容斥+状压)
题意 https://www.cometoj.com/contest/52/problem/C?problem_id=2416 思路 这里提供一种容斥的写法(?好像网上没看到这种写法) 题目要求编号为 ...
- BZOJ2669 [cqoi2012]局部极小值 状压DP 容斥原理
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2669 题意概括 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所 ...
- 【bzoj2669】[cqoi2012]局部极小值 容斥原理+状压dp
题目描述 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值. 给出所有局部极小值的位置,你的任 ...
- 洛谷$P$3160 局部极小值 $[CQOI2012]$ 状压$dp$
正解:状压$dp$ 解题报告: 传送门! 什么神仙题昂,,,反正我是没有想到$dp$的呢$kk$,,,还是太菜了$QAQ$ 首先看数据范围,一个4×7的方格,不难想到最多有8个局部极小值,过于显然懒得 ...
- HDU5731 Solid Dominoes Tilings 状压dp+状压容斥
题意:给定n,m的矩阵,就是求稳定的骨牌完美覆盖,也就是相邻的两行或者两列都至少有一个骨牌 分析:第一步: 如果是单单求骨牌完美覆盖,请先去学基础的插头dp(其实也是基础的状压dp)骨牌覆盖 hiho ...
随机推荐
- UIImage 内存细节
最近的一个项目,有大量的scrollView+imageView,当iPad启动较多程序,再启动自己的这个程序的时候,就爆内存退出了-- 后来把所有的生成图片的方法,全部由imageNamed改成了i ...
- bzoj千题计划244:bzoj3730: 震波
http://www.lydsy.com/JudgeOnline/problem.php?id=3730 点分树内对每个节点动态维护2颗线段树 线段树以距离为下标,城市的价值为权值 对于节点x的两棵线 ...
- SQL语句取多列的最小值(排除0)
经常遇到获取数据表中多个列的最小值和最大值,例如: 获取这 4个价格的最小值和最大值: SELECT( SELECT min(minPrice) FROM ( VALUES (IIF(MarketSi ...
- linux下面根据不同的日期创建不同文件,一般用户数据库的备份的shell编程
[root@www scripts]# vi sh03.sh #!/bin/bash # Program: # Program creates three files, which named by ...
- Python内置函数(25)——frozenset
英文文档: class frozenset([iterable]) Return a new frozenset object, optionally with elements taken from ...
- 关于tomcat和jetty的乱码问题
现象:windows 下的tomcat和jetty默认安装都有问题,linux下的没有问题. 分析:操作系统字符集发生作用了,程序有些处理可能使用了该默认字符集,导致两边现象不一致,建议排查,先尝试通 ...
- IDE-Ecplise-代码注释 模版 编码规范 配色
说明: 代码注释主要用于方便代码后期维护,编码规范,增加代码阅读性和维护性.因网上看到的很多博客中片段局多,故整理后重写一篇,方便交流学习. 先看下加过注释模版后的效果. 如上图所示,创建类,方法和继 ...
- python基础——继承实现的原理
python基础--继承实现的原理 1 继承顺序 class A(object): def test(self): print('from A') class B(A): def test(self) ...
- Java:List集合内的对象进行排序
List集合中的对象进行排序,除了for外,还有java的Collections对象来对摸个集合进行排序的用法. 比如说我有一个List集合,集合元素为: public class TaskAutoE ...
- JavaScript splice() 、slice() 方法
定义和用法 splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目. slice() 方法可从已有的数组中返回选定的元素. 注释:该方法会改变原始数组. 语法 arrayObject. ...