P3160 [CQOI2012]局部极小值
题目
一眼就是状压,接下来就不知道了\(qwq\)
做法
我们能手玩出局部小值最多差不多是\(8,9\)个的样子,\(dp_{i,j}\)为填满\(1~i\)数字,局部小值的状态为\(j\)
第\(k\)个局部极小值填\(i\):\(dp[i][j]=(dp[i][j]+dp[i-1][j^(1<<k-1)])%p\)
不填在局部极小值,显然有些地方不能填\(i\)的,首先还没填的局部极小值不填,其周围也不能填(填\(i\)后后面再填比不符合局部极小值)
我们预处理出每种状态不能填时的位置:\(dp[i][j]=(dp[i][j]+dp[i-1][j]*max(num[j]-i+1,0))%p\)
一顿操作后发现WA了,我们得到的局部极小值可能不是恰好是给出的\(X\)(更多)
容斥原理:Ans=至少多0个极小值-至少多1个极小值+至少多两个极小值......
理解:至少多0个\((x,x+1,x+2,x+3...)-k(x+1,x+2,x+3...)\)其中\(k\)为某些值的系数
填了至少多0个极小值后,有多填的部分那就得减去至少多1个极小值,至少多1个极小值的位置也有很多,就会有一些位置减掉的系数为(k>1),就要又加上
\(dfs\)时加上能被多余的极小值填上的地方换成'X',然后多次做\(dp\)
My complete code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn=31;
const int p=12345678;
const int dx[8]={-1,-1,-1,0,1,1,1,0},dy[8]={-1,0,1,1,1,0,-1,-1};
int n,m,tot;
LL ans;
int x[maxn],y[maxn],num[1<<9],dp[maxn][1<<9];
bool visit[maxn][maxn];
char s[maxn][maxn];
inline int Solve(){
tot=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if (s[i][j]=='X')
x[++tot]=i,
y[tot]=j;
int Up=1<<tot;
for(int i=0;i<Up;i++){
int cnt(0);
memset(visit,0,sizeof(visit));
for(int j=1;j<=tot;++j)
if(!((i>>(j-1))&1)){
visit[x[j]][y[j]]=1;
for(int k=0;k<8;++k){
int xx=x[j]+dx[k];
int yy=y[j]+dy[k];
if(xx>0&&yy>0&&xx<=n&&yy<=m)
visit[xx][yy]=1;
}
}
for(int j=1;j<=n;++j)
for(int k=1;k<=m;++k)
if(visit[j][k])
++cnt;
num[i]=n*m-cnt;
}
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=n*m;++i)
for(int j=0;j<Up;++j){
dp[i][j]=(dp[i][j]+dp[i-1][j]*max(num[j]-i+1,0))%p;
for(int k=1;k<=tot;k++)
if(j&(1<<(k-1)))
dp[i][j]=(dp[i][j]+dp[i-1][j^(1<<k-1)])%p;
}
return dp[n*m][Up-1];
}
void Dfs(int x,int y,int k){
if(y==m+1){
Dfs(x+1,1,k);
return;
}
if(x==n+1){
ans=(ans+(((k&1)==0)?1:-1)*Solve()+p)%p;
return;
}
Dfs(x,y+1,k);
if(s[x][y]!='X'){
bool f=true;
for(int i=0;i<8;i++)
if(s[x+dx[i]][y+dy[i]]=='X'){
f=false;
break;
}
if(f){
s[x][y]='X',
Dfs(x,y+1,k+1),
s[x][y]='.';
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf(" %s",s[i]+1);
Dfs(1,1,0);
printf("%lld\n",ans);
return 0;
}
/*
5 5
.....
...X.
.X...
.....
....X
*/
P3160 [CQOI2012]局部极小值的更多相关文章
- P3160 [CQOI2012]局部极小值 题解(状压DP+容斥)
题目链接 P3160 [CQOI2012]局部极小值 双倍经验,双倍快乐 解题思路 存下来每个坑(极小值点)的位置,以这个序号进行状态压缩. 显然,\(4*7\)的数据范围让极小值点在8个以内(以下示 ...
- BZOJ 2669 Luogu P3160 [CQOI2012]局部极小值 (容斥原理、DP)
题目链接 (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2669 (luogu) https://www.luogu.org/prob ...
- 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 有一 ...
- 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 题意概述:实际上原题意很简洁了我就不写了吧.... 二话不说先观察一下性质,首先棋盘 ...
随机推荐
- 前端性能优化--为什么DOM操作慢? 浅谈DOM的操作以及性能优化问题-重绘重排 为什么要减少DOM操作 为什么要减少操作DOM
前端性能优化--为什么DOM操作慢? 作为一个前端,不能不考虑性能问题.对于大多数前端来说,性能优化的方法可能包括以下这些: 减少HTTP请求(合并css.js,雪碧图/base64图片) 压缩( ...
- android收起软键盘
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);if(imm != null) ...
- sqlplus登入和plsql登入的差别
以下是两种登入方式的截图.用sqlplus登入须要输入主机字: 假设是用本机的SQL*Plus连接本机的数据库.则"主机字符串"能够为空. 假设是从远程连接xp的oracle数据库 ...
- RealProxy AOP过滤方法的参数
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...
- MySQL_使用时遇到的问题汇总
一.data too long for column 'name' at row 1 1.现象:把数据库的字符集编码设置为utf-8,通过DOS界面向表的某一列插入汉字时会遇到类似 data too ...
- oracle字符乱码的解决方法
原因分析: 客户端字符集就是为了让数据库知道我们传递过去的字符是属于哪种字符集,以便于Oracle在存储字符时进行相应的编码映射(查看客户端字符集通过查找注册表中的NLS_LANG键).在客户端查询数 ...
- Eclipse配置总结
按照公司要求,开发环境使用Eclipse Juno版本,需要安装maven插件和RTC插件. 经过一下午的尝试,总结经验教训: 1.eclipse安装maven的m2ec ...
- (C#)为应用程式设定运行权限(System.Security类下的GenericIdentity,GenericPrincipal,PrincipalPermission)
最近看书<编写高质量代码改善C#程序的157个建议>,知识点备忘: System.Security.Principal.GenericIdentity==>表示一般用户 System ...
- 浅谈Java数据结构和算法
今天的突然看集合底层的时候发现了好多算法和数据结构.再次就比较一下和汇总一下. 数据结构分类:线性结构和非线性结构 问题一: 什么是线性和非线性: 我个人的理解是:数据结构中线性结构指的是数据元素之间 ...
- 线段树专题—HDU1698 Just a Hook
题意:t组数据,给一个n.m表示n长度的钩和m次操作.初始钩子的每单位长度的价值为1,接下来输入 x,y,k 的操作把钩子[x,y]区间的价值替换为k,求m次操作后钩子的价值为多少 分析:成段替换.最 ...