2669: [cqoi2012]局部极小值

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 667  Solved: 350

Description

有一个nm列的整数矩阵,其中1到nm之间的每个整数恰好出现一次。如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值。
给出所有局部极小值的位置,你的任务是判断有多少个可能的矩阵。

Input

输入第一行包含两个整数nm(1<=n<=4, 1<=m<=7),即行数和列数。以下n行每行m个字符,其中“X”表示局部极小值,“.”表示非局部极小值。

Output

输出仅一行,为可能的矩阵总数除以12345678的余数。

Sample Input

3 2
X.
..
.X

Sample Output

60

HINT

Source

【分析】

  我好蠢啊。。。

  保证每个数各不相同,又有大小关系,那么、、数字从小到大填。

  其实局部极小值<=8的,这个可以状压,$f[i][j]$表示填了前i个数,局部极小值被填的状态是j的方案数。

  有:

  $f[i][j]=f[i-1][j]*(p[j]-i+1)+f[i-1][j-(1<<X)]$

  但是,还要保证一点是非极小值一定非极小,上面没有保证,

  所以枚举哪些非极小弄成了极小,容斥算出正确答案即可。

  复杂度?$O(dfs*n*m*8*2^8)$大概是这样吧。。数据很小嘛。。。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Mod 12345678
#define LL long long int a[][],num[][],p[];
int n,m;
int bx[]={,,,-,,,-,,-},
by[]={,,,,-,,-,-,};
char s[];
bool vis[][];
LL f[][],ans=; LL get_ans()
{
int cnt=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) if(a[i][j]==) num[i][j]=++cnt;
for(int k=;k<=(<<cnt)-;k++)
{
for(int i=;i<=n;i++) for(int j=;j<=m;j++) vis[i][j]=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) if(a[i][j]==&&((<<num[i][j]-)&k)==)
{
for(int l=;l<=;l++)
{
int nx=i+bx[l],ny=j+by[l];
vis[nx][ny]=;
}
}
p[k]=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) if(vis[i][j]&&a[i][j]==) {p[k]++;vis[i][j]=;}
for(int i=;i<=cnt;i++) if((<<i-)&k) p[k]++;
}
memset(f,,sizeof(f));
f[][]=;
for(int i=;i<=n*m;i++)
for(int j=;j<=(<<cnt)-;j++)
{
f[i][j]=f[i-][j]*(p[j]-i+);f[i][j]%=Mod;
for(int k=;k<=cnt;k++) if((<<k-)&j)
{
f[i][j]+=f[i-][j-(<<k-)];
f[i][j]%=Mod;
}
}
return f[n*m][(<<cnt)-];
} void dfs(int x,int y,int f)
{
if(y==m+) {dfs(x+,,f);return;}
if(x==n+)
{
ans+=f*get_ans();
ans=(ans%Mod+Mod)%Mod;
return;
}
if(a[x][y]==) {dfs(x,y+,f);return;}
bool ok=;
for(int i=;i<=;i++)
{
int nx=x+bx[i],ny=y+by[i];
if(nx<||nx>n||ny<||ny>m) continue;
if(a[nx][ny]==) {ok=;break;}
}
if(ok)
{
a[x][y]=;
dfs(x,y+,-f);
a[x][y]=;
}
dfs(x,y+,f);
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",s+);
for(int j=;j<=m;j++)
{
if(s[j]=='X') a[i][j]=;
else a[i][j]=;
}
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) if(a[i][j]==)
{
for(int k=;k<=;k++)
{
int nx=i+bx[i],ny=j+by[i];
if(nx<||nx>n||ny<||ny>m) continue;
if(a[nx][ny]==) {printf("0\n");return ;}
}
}
// memset(vis,1,sizeof(vis));
dfs(,,);
printf("%lld\n",ans);
return ;
}

2017-04-06 10:08:51

【BZOJ 2669】 2669: [cqoi2012]局部极小值 (状压DP+容斥原理)的更多相关文章

  1. BZOJ2669 [cqoi2012]局部极小值 状压DP 容斥原理

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2669 题意概括 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所 ...

  2. BZOJ 2669 CQOI2012 局部极小值 状压dp+容斥原理

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2669 题意概述:实际上原题意很简洁了我就不写了吧.... 二话不说先观察一下性质,首先棋盘 ...

  3. bzoj2669 [cqoi2012]局部极小值 状压DP+容斥

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2669 题解 可以发现一个 \(4\times 7\) 的矩阵中,有局部最小值的点最多有 \(2 ...

  4. 【BZOJ-2669】局部极小值 状压DP + 容斥原理

    2669: [cqoi2012]局部极小值 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 561  Solved: 293[Submit][Status ...

  5. 【uoj#37/bzoj3812】[清华集训2014]主旋律 状压dp+容斥原理

    题目描述 求一张有向图的强连通生成子图的数目对 $10^9+7$ 取模的结果. 题解 状压dp+容斥原理 设 $f[i]$ 表示点集 $i$ 强连通生成子图的数目,容易想到使用总方案数 $2^{sum ...

  6. 【bzoj2560】串珠子 状压dp+容斥原理

    题目描述 有 $n$ 个点,点 $i$ 和点 $j$ 之间可以连 $0\sim c_{i,j}$ 条无向边.求连成一张无向连通图的方案数模 $10^9+7$ .两个方案不同,当且仅当:存在点对 $(i ...

  7. BZOJ.4145.[AMPPZ2014]The Prices(状压DP)

    BZOJ 比较裸的状压DP. 刚开始写麻烦惹... \(f[i][s]\)表示考虑了前\(i\)家商店,所买物品状态为\(s\)的最小花费. 可以写求一遍一定去\(i\)商店的\(f[i]\)(\(f ...

  8. BZOJ.3058.四叶草魔杖(Kruskal 状压DP)

    题目链接 \(2^{16}=65536\),可以想到状压DP.但是又有\(\sum A_i\neq 0\)的问题.. 但是\(2^n\)这么小,完全可以枚举所有子集找到\(\sum A_i=0\)的, ...

  9. bzoj 5299: [Cqoi2018]解锁屏幕 状压dp+二进制

    比较简单的状压 dp,令 $f[S][i]$ 表示已经经过的点集为 $S$,且最后一个访问的位置为 $i$ 的方案数. 然后随便转移一下就可以了,可以用 $lowbit$ 来优化一下枚举. code: ...

  10. 4455: [Zjoi2016]小星星|状压DP|容斥原理

    OrzSDOIR1ak的晨神 能够考虑状压DP枚举子集,求出仅仅保证连通性不保证一一相应的状态下的方案数,然后容斥一下就是终于的答案 #include<algorithm> #includ ...

随机推荐

  1. 原生js写Ajax

    //原生js写ajax就像打电话 //打电话分下面4步//1.拿出手机//2.拨号//3.说话//4.挺对方说话 //ajax也分下面4步//1.创建ajax对象//2.连接到服务器//3.发送请求( ...

  2. python学习笔记(十)之格式化字符串

    格式化字符串,可以使用format方法.format方法有两种形式参数,一种是位置参数,一种是关键字参数. >>> '{0} {1}'.format('Hello', 'Python ...

  3. 关于linux下crontab mysql备份出来的数据为0字节的问题

    问题出在计划任务所执行的脚本上! 脚本中的调用的指令应该都写全路径~ 实例: # crontab -c 编辑下的内容 30 18 * * * /root/backup.sh 意思为:每天18:30执行 ...

  4. CentOS7防火墙fiewall用法

    CentOS7与以前常用的CentOS6还是有一些不同之处的,比如在设置开放端口的时候稍许有些不同,常用的iptables命令已经被 firewalld代替.这几天正好有在CentOS7系统中玩Sea ...

  5. ogg数据初始化历程记录

    之前,源端数据表结构发生改变,不知道前面的同事是怎么搞得(生成的数据定义文件不对,还是没有把进程启动),造成进程停止20天,然后重启复制进程,对比源端和目标端数据有差异(总共差10000多条数据),问 ...

  6. 2-Python基础语法-内存管理-运算符-程序控制

    目录 1 Python 基础语法 1.1 注释 1.2 缩进 1.3 续行 1.4 标识符 1.5 转义序列 1.6 数字 1.7 字符串 1.8 其他 2 Python 运算符 2.1 赋值运算符 ...

  7. SQL 变量 条件查询 插入数据

    (本文只是总结网络上的教程) 在操作数据库时 SQL语句中难免会用到变量 比如 在條件值已知的情況下 INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值 ...

  8. 64_s1

    SAASound-3.2-17.fc26.i686.rpm 13-Feb-2017 22:13 27650 SAASound-3.2-17.fc26.x86_64.rpm 13-Feb-2017 23 ...

  9. hdu 4347 The Closest M Points (kd树)

    版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4347 题意: 求k维空间中离所给点最近的m个点,并按顺序输出  . 解法: kd树模板题 . 不懂kd树的可以先看看这个 . 不多说, ...

  10. 11.python3标准库--使用进程、线程和协程提供并发性

    ''' python提供了一些复杂的工具用于管理使用进程和线程的并发操作. 通过应用这些计数,使用这些模块并发地运行作业的各个部分,即便是一些相当简单的程序也可以更快的运行 subprocess提供了 ...