[CQOI2012]局部极小值
注意到\(4\times 7\)的矩阵的局部极小值最多只有8个,可以状压。
设\(f[i][sta]\)表示从小到大填数,当前填到\(i\),极小值的填充状态为\(sta\)的方案数。
考虑到由于是从小到大填数,每个极小值位置没填时,其四周的位置也不能填。
那么可以分情况讨论:
当前填在极小值位置上,\(f[i][sta]+=f[i-1][sta-(1<<j)]\).其中\(j\)为枚举到的位置。
否则,处理出当前状态下可以填的位置数\(num\),以前填了\(i-1\)个,转移:\(f[i][sta]+=f[i-1][sta]*(num-(i-1))\).
最后的答案为\(f[n*m][(1<<num)-1]\),\(num\)为极小值的个数。
但是,可以发现,题目要求极小值只有输入的那几个,但是这样转移可能会在随便填的地方产生新的极小值。
拿这个答案减去多了1个极小值的方案,就可以排除多一个极小值的错误,但是发现多两个的多减了一个,在加上……
其实就是容斥了一下,即原答案\(-\)多了一个的方案\(+\)多了两个的方案.....
然后多了几个的方案可以暴力枚举多了哪几个,添加到原图中,然后和上面一样的dp出来。
#include<bits/stdc++.h>
using namespace std;
#define int long long
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);x*=f;
}
void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar((x%10)^48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}
const int dx[]={0,1,1,1,0,-1,-1,-1,0};
const int dy[]={0,1,0,-1,1,1,0,-1,-1};
const int mod = 12345678;
int n,m,mp[10][10],f[30][(1<<9)+10],ans,vx[10],vy[10],num[1000],c[5][8];
char s[10];
int check(int x,int y) {return x>=1&&x<=n&&y>=1&&y<=m;}
int calc() {
memset(f,0,sizeof f);f[0][0]=1;vx[0]=0,vy[0]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]) vx[++vx[0]]=i,vy[++vy[0]]=j;
for(int s=0;s<(1<<vx[0]);s++) {
memset(c,0,sizeof c);
for(int i=1;i<=vx[0];i++)
if(!(s&(1<<(i-1)))) {
for(int x,y,k=1;k<=8;k++)
if(check(x=vx[i]+dx[k],y=vy[i]+dy[k])) c[x][y]=1;
c[vx[i]][vy[i]]=1;
}num[s]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
num[s]+=c[i][j]^1;
}
for(int i=1;i<=n*m;i++)
for(int s=0;s<(1<<vx[0]);s++) {
(f[i][s]+=f[i-1][s]*max(0ll,num[s]-(i-1))%mod)%=mod;
for(int j=1;j<=vx[0];j++)
if(s&(1<<(j-1))) f[i][s]=(f[i][s]+f[i-1][s^(1<<(j-1))])%mod;
}
return f[n*m][(1<<vx[0])-1];
}
//void debug() {for(int i=1;i<=n;i++,puts("")) for(int j=1;j<=m;j++,putchar(' ')) printf("%d",mp[i][j]);}
void dfs(int x,int y,int f) {
if(y==m+1) return dfs(x+1,1,f),void();
if(x==n+1) return ans=(ans+calc()*f)%mod,/*debug()*/void();
dfs(x,y+1,f);int flag=0;
for(int i=1;i<=8;i++)
if(check(x+dx[i],y+dy[i])&&mp[x+dx[i]][y+dy[i]]) {flag=1;break;}
if(mp[x][y]) flag=1;
if(!flag) mp[x][y]=1,dfs(x,y+1,-f),mp[x][y]=0;
}
void solve () {
read(n),read(m);
for(int i=1;i<=n;i++) {
scanf("%s",s+1);//cout<<s+1<<endl;
for(int j=1;j<=m;j++) if(s[j]=='X') mp[i][j]=1;
}//debug();puts("");
dfs(1,1,1);write((ans%mod+mod)%mod);
}
signed main() {solve();return 0;}
[CQOI2012]局部极小值的更多相关文章
- bzoj 2669 [cqoi2012]局部极小值 DP+容斥
2669: [cqoi2012]局部极小值 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 838 Solved: 444[Submit][Status ...
- bzoj2669[cqoi2012]局部极小值 容斥+状压dp
2669: [cqoi2012]局部极小值 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 774 Solved: 411[Submit][Status ...
- [BZOJ2669] [cqoi2012]局部极小值
[BZOJ2669] [cqoi2012]局部极小值 Description 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点) ...
- 【BZOJ 2669】 2669: [cqoi2012]局部极小值 (状压DP+容斥原理)
2669: [cqoi2012]局部极小值 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 667 Solved: 350 Description 有一 ...
- P3160 [CQOI2012]局部极小值
题目 P3160 [CQOI2012]局部极小值 一眼就是状压,接下来就不知道了\(qwq\) 做法 我们能手玩出局部小值最多差不多是\(8,9\)个的样子,\(dp_{i,j}\)为填满\(1~i\ ...
- P3160 [CQOI2012]局部极小值 题解(状压DP+容斥)
题目链接 P3160 [CQOI2012]局部极小值 双倍经验,双倍快乐 解题思路 存下来每个坑(极小值点)的位置,以这个序号进行状态压缩. 显然,\(4*7\)的数据范围让极小值点在8个以内(以下示 ...
- BZOJ2669 [cqoi2012]局部极小值 状压DP 容斥原理
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2669 题意概括 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所 ...
- 【bzoj2669】[cqoi2012]局部极小值 容斥原理+状压dp
题目描述 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值. 给出所有局部极小值的位置,你的任 ...
- BZOJ 2669 CQOI2012 局部极小值 状压dp+容斥原理
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2669 题意概述:实际上原题意很简洁了我就不写了吧.... 二话不说先观察一下性质,首先棋盘 ...
随机推荐
- 揭开js之constructor属性的神秘面纱
揭开 constructor 在 Javascript 语言中,constructor 属性是专门为 function 而设计的,它存在于每一个 function 的prototype 属性中.这个 ...
- Python的Bottle框架中实现最基本的get和post的方法的教程
这篇文章主要介绍了Python的Bottle框架中实现最基本的get和post的方法的教程,Bottle框架在Python开发者中的人气很高,需要的朋友可以参考下 1.GET方式: # -*- cod ...
- python3 练习题100例 (十一)
题目十一:举例证明角谷猜想:以一个正整数N为例,如果N为偶数,就将它变为N/2,如果除后变为奇数,则将它乘3加1(即3N+1).不断重复这样的运算,经过有限步后,一定可以得到1. #!/usr/bin ...
- 查询如下课程平均成绩和及格率的百分数(用"1行"显示): 企业管理(001),马克思(002),OO&UML (003),数据库(004)
SELECT SUM(CASE WHEN C# ='001' THEN score ELSE 0 END)/SUM(CASE C# WHEN '001' THEN 1 ELSE 0 END) AS 企 ...
- Android面试收集录 2D绘图与动画技术
1.如何在Android应用程序的窗口上绘制图形? 继承View 实现View中的onDraw()方法 2.如何绘制圆,空心椭圆? canvas.drawArc或canvas.drawCircle方法 ...
- 3 python3 编码解码问题 upd接受数据
1.python3下的中文乱码:send_data.encode("utf-8") from socket import * udp_socket = socket(AF_INET ...
- 使用USB Key(加密狗)实现身份认证
首先你需要去买一个加密狗设备,加密狗是外形酷似U盘的一种硬件设备! 这里我使用的坚石诚信公司的ET99产品 公司项目需要实现一个功能,就是客户使用加密狗登录, 客户不想输入任何密码之类的东西,只需要插 ...
- 安装Sql Server 2008的时候报错说找不到某个安装文件
在安装Sql Server 2008的时候,报错说找不到某个安装文件,但是这个文件明明在那,百思不得其解. 最后看到一个老外的文章里面说,你要确认,你能访问到这个文件 ...
- 从一个线上服务器警告谈谈backlog
缘起 双十一如期而至,此时的我因为在处理客户的一个问题已经陷入了忙碌.突然,不断接到驻场实施发来的反馈,都是相同的反馈--"客户端操作缓慢". 我现在负责的服务器是一台接口服务器, ...
- 教你用Bootstrap开发漂亮的前端界面
Bootstrap介绍: Bootstrap 是最受欢迎的 HTML.CSS 和 JS 框架,用于开发响应式布局.移动设备优先的 WEB 项目. Bootstrap的特点: 一.预处理脚本:虽然可以直 ...