HDU5838 Mountain(状压DP + 容斥原理)
题目
Source
http://acm.hdu.edu.cn/showproblem.php?pid=5838
Description
Zhu found a map which is a N∗M rectangular grid.Each cell has a height and there are no two cells which have the same height. But this map is too old to get the clear information,so Zhu only knows cells which are valleys.
A cell is called valley only if its height is less than the heights of all its adjacent cells.If two cells share a side or a corner they are called adjacent.And one cell will have eight adjacent cells at most.
Now give you N strings,and each string will contain M characters.Each character will be '.' or uppercase 'X'.The j-th character of the i-th string is 'X' if the j-th cell of the i-th row in the mountain map is a valley, and '.' otherwise.Zhu wants you to calculate the number of distinct mountain maps that match these strings.
To make this problem easier,Zhu defines that the heights are integers between 1 and N∗M.Please output the result modulo 772002.
Input
The input consists of multiple test cases.
Each test case begins with a line containing two non-negative integers N and M. Then N lines follow, each contains a string which contains M characters. (1≤N≤5,1≤M≤5).
Output
For each test case, output a single line "Case #x: y", where x is the case number, starting from 1. And y is the answer after module 772002.
Sample Input
2 4
.X..
...X
4 2
X.
..
..
X.
1 2
XX
Sample Output
Case #1: 2100
Case #2: 2520
Case #3: 0
分析
题目大概说给一张大小n*m由'X'或'.'标记的图,要在其各个位置填入1到n*m这几个数,满足'X'填入的数是极小的(小于周围八个数)且'.'填入的数不是极小的,求有几种填法。
好难的感觉。。
考虑把数从小到大依次填入:
- dp[i][S]表示当前已经填入数字1...i,且已经被填数的'X'集合为S的方案数(因为合法的'X'最多有9个所以用9位二进制压缩表示S即可)
通过将i+1填入转移到dp[i+1]的状态:
- 可以选择把i+1填入下一个还没被填的'X'位置x
- 也可以填入'.'的位置,这个点'.'的位置不能是未填的'X'周围,因为是从小到大填数的
这样子得到的方案数得到的不是答案要的方案数,因为它还包含了'.'填入的数是极小的,这个用容斥原理搞一下,具体就是用一个dfs搜出所有合法的'.'变为'X'的情况,奇数个减,偶数个加。。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n,m; int dx[]={0,0,1,-1,1,-1,1,-1};
int dy[]={1,-1,0,0,1,-1,-1,1};
char map[5][5]; long long d[26][1<<9];
int pos[1<<9],siz[1<<9]; long long dp(){
int cnt=0,x[9],y[9];
for(int i=0; i<n; ++i){
for(int j=0; j<m; ++j){
if(map[i][j]=='X'){
x[cnt]=i; y[cnt]=j;
++cnt;
}
}
}
memset(siz,0,sizeof(siz));
for(int s=0; s<(1<<cnt); ++s){
for(int i=0; i<cnt; ++i){
if(s>>i&1){
map[x[i]][y[i]]='Y';
++siz[s];
}
}
int res=0;
for(int i=0; i<n; ++i){
for(int j=0; j<m; ++j){
if(map[i][j]!='.') continue;
bool flag=1;
for(int k=0; k<8; ++k){
int nx=i+dx[k],ny=j+dy[k];
if(nx<0 || nx>=n || ny<0 ||ny>=m) continue;
if(map[nx][ny]=='X'){
flag=0;
break;
}
}
if(flag) ++res;
}
}
pos[s]=res;
for(int i=0; i<cnt; ++i){
if(s>>i&1){
map[x[i]][y[i]]='X';
}
}
} memset(d,0,sizeof(d));
d[0][0]=1;
for(int i=0; i<n*m; ++i){
for(int j=0; j<(1<<cnt); ++j){
if(d[i][j]==0) continue;
for(int k=0; k<cnt; ++k){
if(j>>k&1) continue;
d[i+1][j^(1<<k)]+=d[i][j];
d[i+1][j^(1<<k)]%=772002;
}
d[i+1][j]+=d[i][j]*(pos[j]-i+siz[j]);
d[i+1][j]%=772002;
}
}
return d[n*m][(1<<cnt)-1];
} long long ans;
void dfs(int z,int k){
if(z==n*m){
if(k&1) ans-=dp();
else ans+=dp();
ans%=772002;
return;
}
int x=z/m,y=z%m;
bool flag=(map[x][y]!='X');
for(int i=0; i<8; ++i){
int nx=x+dx[i],ny=y+dy[i];
if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
if(map[nx][ny]=='X'){
flag=0;
break;
}
}
if(flag){
map[x][y]='X';
dfs(z+1,k+1);
map[x][y]='.';
}
dfs(z+1,k);
} bool check(){
for(int i=0; i<n; ++i){
for(int j=0; j<m; ++j){
if(map[i][j]=='.') continue;
for(int k=0; k<8; ++k){
int nx=i+dx[k],ny=j+dy[k];
if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
if(map[nx][ny]=='X') return 0;
}
}
}
return 1;
} int main(){
int cse=0;
while(~scanf("%d%d",&n,&m)){
for(int i=0; i<n; ++i){
for(int j=0; j<m; ++j){
scanf(" %c",&map[i][j]);
}
}
if(!check()){
printf("Case #%d: 0\n",++cse);
continue;
}
ans=0;
dfs(0,0);
if(ans<0) ans+=772002;
printf("Case #%d: %lld\n",++cse,ans);
}
return 0;
}
HDU5838 Mountain(状压DP + 容斥原理)的更多相关文章
- 【uoj#37/bzoj3812】[清华集训2014]主旋律 状压dp+容斥原理
题目描述 求一张有向图的强连通生成子图的数目对 $10^9+7$ 取模的结果. 题解 状压dp+容斥原理 设 $f[i]$ 表示点集 $i$ 强连通生成子图的数目,容易想到使用总方案数 $2^{sum ...
- 【bzoj2560】串珠子 状压dp+容斥原理
题目描述 有 $n$ 个点,点 $i$ 和点 $j$ 之间可以连 $0\sim c_{i,j}$ 条无向边.求连成一张无向连通图的方案数模 $10^9+7$ .两个方案不同,当且仅当:存在点对 $(i ...
- BZOJ2669 [cqoi2012]局部极小值 状压DP 容斥原理
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2669 题意概括 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所 ...
- 4455: [Zjoi2016]小星星|状压DP|容斥原理
OrzSDOIR1ak的晨神 能够考虑状压DP枚举子集,求出仅仅保证连通性不保证一一相应的状态下的方案数,然后容斥一下就是终于的答案 #include<algorithm> #includ ...
- 【BZOJ 2669】 2669: [cqoi2012]局部极小值 (状压DP+容斥原理)
2669: [cqoi2012]局部极小值 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 667 Solved: 350 Description 有一 ...
- 【BZOJ-2669】局部极小值 状压DP + 容斥原理
2669: [cqoi2012]局部极小值 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 561 Solved: 293[Submit][Status ...
- BZOJ 2669 CQOI2012 局部极小值 状压dp+容斥原理
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2669 题意概述:实际上原题意很简洁了我就不写了吧.... 二话不说先观察一下性质,首先棋盘 ...
- BZOJ3812 主旋律(状压dp+容斥原理)
设f[S]为S点集是SCC的方案数.考虑通过去掉不合法方案转移.可以枚举入度为0的SCC所含点集S',这样显然S^S'内部的边和由S'连向S^S'的边删还是不删任选.但是这样无法保证S'包含所有入度为 ...
- [BZOJ3812]主旋律:状压DP+容斥原理
分析 Miskcoo orz 令\(f[S]\)表示使得\(S\)这个点集强连通的方案数. 然后呢?不会了 考虑到将一个有向图SCC缩点后,得到的新图是一个DAG,所以我们可以类比带标号DAG计数的解 ...
随机推荐
- D2js 是如何处理并发的
d2js 运行于 servlet 容器,如tomcat,由于容器自身支持并发,似乎 d2js 只要使用 nashorn 运行脚本即可.这样我们得到最简单的实现方式: 在该方式中,nashorn引擎仅存 ...
- Python中函数、类、模块和包的调用
初学python阶段,大多数人对函数.类.模块和包的调用都搞得不是很清楚,这篇随笔就简单的进行说明. (1)函数 当函数定义好之后,可以直接调用. 比如:def summ(add1,add2),那么 ...
- web自动化工具-开篇
web自动化工具-开篇 最近几年,前端技术风一样的速度迭代更新,各种框架工具雨后春笋般涌现,作为一个平凡的开发者,也只能在洪流中沉沉浮浮,微不足道,以前前端叫做切图仔.美工,如今改了称号叫前端工程师, ...
- Android Notification通知详解
根据activity的生命周期,在activity不显示时,会执行onStop函数(比如按下home键),所以你在onStop函数(按退出键除外)里面把notification放在通知栏里,再此显示时 ...
- robotframework,selenium启动不了打不开浏览器的问题访问不了网页
由于最近发现咨询火狐浏览器打不开的问题比较多,现罗列几点解决办法. 1,由于selenium更新3.0的原因导致不在默认支持火狐浏览器,且支持的火狐浏览器大概在45以上的版本,所以很多都由于这个原因导 ...
- IE浏览器版本判断 HTML代码
<!--[if IE 6.0]> <div id="noie6" style="z-index: 20002;border: 1px solid #F7 ...
- Unity MonoDevelop一打开未响应
在学习Untiy的时候,使用内置的MonoDevelop开发工具.本来就不好用,经常出现未响应的情况,然后重启解决.终于有一次莫名其妙的崩溃了,在Unity打开该IDE就未响应,但直接打开MonoDe ...
- MySQL · 答疑解惑 · MySQL 锁问题最佳实践
http://mysql.taobao.org/monthly/2016/03/10/ 前言 最近一段时间处理了较多锁的问题,包括锁等待导致业务连接堆积或超时,死锁导致业务失败等,这类问题对业务可能会 ...
- Erlang C1500K长连接推送服务-内存
上篇 Erlang C1500K长连接推送服务-性能 提到:150w连接,使用了23GB内存,每个连接占用15KB,约一半是内核使用. 大概分析一下: 1. Erlang 节点 12GB,内部因为有内 ...
- 一篇笔记整理JVM工作原理
首先要了解的 >>数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型. 基本类型的变量保存原始值,即:他代表的值就是数值本身:而引用类型的变量保存引用值.“引用值”代表了 ...