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 ...
随机推荐
- new malloc和delete free 的区别
今天看了一个面试题:问new 和 malloc, delete 和 free 的区别,扭捏了半天,也没说完全:现总结如下: 1.先看看new 和 delete 看一个例子: <span styl ...
- Codeforces 240 F. TorCoder
F. TorCoder time limit per test 3 seconds memory limit per test 256 megabytes input input.txt output ...
- codevs 3981 动态最大子段和
3981 动态最大子段和 http://codevs.cn/problem/3981/ 题目等级 : 钻石 Diamond 题目描述 Description 题目还是简单一点好... 有n个 ...
- wyh的数列~(坑爹题目)
链接:https://www.nowcoder.com/acm/contest/93/K来源:牛客网 题目描述 wyh学长特别喜欢斐波那契数列,F(0)=0,F(1)=1,F(n)=F(n-1)+F( ...
- 解决忽略VScode中Python插件pylint报错的问题
pylint是VScode中python自带的插件,可以帮助代码规范,美观. 但是有些报错是你不想看到的,你可以选择性的忽略. 例如,在re.compile()中,可以添加参数re.S使. 匹配任意字 ...
- OpenID Connect + OAuth2.0
一.问题的提出 现代应用程序或多或少都是如下这样的架构: 在这种情况下,前端.中间层和后端都需要进行验证和授权来保护资源,所以不能仅仅在业务逻辑层或者服务接口层来实现基础的安全功能.为了解决这样的问题 ...
- Python之协程
前言 在操作系统中进程是资源分配的最小单位,线程是CPU调度的最小单位.按道理来说我们已经算是把cpu的利用率提高很多了.但是我们知道无论是创建多进程还是创建多线程来解决问题,都要消耗一定的时间来创建 ...
- webpack打包性能优化
1. 使用 gzip 压缩打包后的 js 文件 这个方法优化浏览器下载时的文件大小(打包后的文件大小没有改变) webpack.config.prod.js 中 var CompressionWebp ...
- 基于哈夫曼编码的文件压缩(c++版)
本博客由Rcchio原创 我了解到很多压缩文件的程序是基于哈夫曼编码来实现的,所以产生了自己用哈夫曼编码写一个压缩软件的想法,经过查阅资料和自己的思考,我用c++语言写出了该程序,并通过这篇文章来记录 ...
- SourceTree 01 - git 客户端介绍
SourceTree - git客户端介绍 SourceTree系列第1篇 --->> SourceTree 01 - git 客户端介绍(http://www.cnblogs.com/g ...