题目链接

(bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2669

(luogu) https://www.luogu.org/problem/P3160

题解

这道题充分暴露了我的菜。。

显然两个局部极小值点不能相邻,所以最多有\(8\)个局部极小值。

然后考虑容斥掉.不能成为局部极小值的限制,那么就变成钦定某些位置一定是局部极小值,其余不限,求方案数。

然后这个可以状压DP,考虑从小到大加入每个数,然后就很好求了。

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<iostream>
#include<vector>
using namespace std; const int P = 12345678;
const int dx[8] = {1,0,-1,0,1,1,-1,-1},dy[8] = {0,1,0,-1,1,-1,-1,1};
vector<int> kx,ky;
int bitcnt[(1<<8)+3];
char a[7][11];
char b[7][11];
int num[(1<<8)+3];
int dp[31][(1<<8)+3];
int n,m,cnt,ans; bool check(int x,int y,int typ)
{
bool ret = true;
for(int i=0; i<8; i++)
{
int xx = x+dx[i],yy = y+dy[i];
if(xx>0&&xx<=n&&yy>0&&yy<=m)
{
if(typ==0) {if(a[xx][yy]=='X') {return false;}}
if(typ==1) {if(b[xx][yy]=='X') {return false;}}
}
}
return true;
} int calc()
{
kx.clear(); ky.clear();
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
if(a[i][j]=='X') {kx.push_back(i); ky.push_back(j);}
}
}
for(int i=0; i<(1<<kx.size()); i++)
{
for(int j=0; j<kx.size(); j++)
{
if(!(i&(1<<j))) {b[kx[j]][ky[j]] = 'X';}
}
num[i] = 0;
for(int j=1; j<=n; j++)
{
for(int k=1; k<=m; k++)
{
bool ok = check(j,k,1);
if((ok && a[j][k]!='X')) num[i]++;
}
}
num[i] += bitcnt[i];
for(int j=0; j<kx.size(); j++) {b[kx[j]][ky[j]] = '.';}
}
dp[0][0] = 1;
for(int i=0; i<n*m; i++)
{
for(int j=0; j<(1<<kx.size()); j++)
{
if(dp[i][j])
{
dp[i+1][j] = (dp[i+1][j]+dp[i][j]*(num[j]-i))%P;
for(int k=0; k<kx.size(); k++)
{
if(!(j&(1<<k)))
{
dp[i+1][j|(1<<k)] = (dp[i+1][j|(1<<k)]+dp[i][j])%P;
}
}
}
}
}
int ret = dp[n*m][(1<<kx.size())-1];
for(int i=0; i<=n*m; i++) for(int j=0; j<(1<<kx.size()); j++) dp[i][j] = 0;
return ret;
} void dfs(int x,int y,int dep)
{
if(x==n+1)
{
int tmp = calc();
if((dep-cnt)&1) {ans = ans-tmp<0 ? ans-tmp+P : ans-tmp;}
else {ans = ans+tmp>=P ? ans+tmp-P : ans+tmp;}
return;
}
int xx = x,yy = y+1; if(yy>m) {yy = 1; xx++;}
if(a[x][y]=='X')
{
bool f = check(x,y,0);
if(f) {dfs(xx,yy,dep+1);}
}
else
{
a[x][y] = 'X';
bool f = check(x,y,0);
if(f) {dfs(xx,yy,dep+1);}
a[x][y] = '.';
dfs(xx,yy,dep);
}
} int main()
{
for(int i=1; i<(1<<8); i++) bitcnt[i] = bitcnt[i>>1]+(i&1);
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) b[i][j] = '.';
for(int i=1; i<=n; i++) scanf("%s",a[i]+1);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++) {if(a[i][j]=='X') cnt++;}
}
if(cnt>8) {printf("0"); return 0;}
dfs(1,1,0);
printf("%d\n",ans);
return 0;
}

BZOJ 2669 Luogu P3160 [CQOI2012]局部极小值 (容斥原理、DP)的更多相关文章

  1. P3160 [CQOI2012]局部极小值 题解(状压DP+容斥)

    题目链接 P3160 [CQOI2012]局部极小值 双倍经验,双倍快乐 解题思路 存下来每个坑(极小值点)的位置,以这个序号进行状态压缩. 显然,\(4*7\)的数据范围让极小值点在8个以内(以下示 ...

  2. P3160 [CQOI2012]局部极小值

    题目 P3160 [CQOI2012]局部极小值 一眼就是状压,接下来就不知道了\(qwq\) 做法 我们能手玩出局部小值最多差不多是\(8,9\)个的样子,\(dp_{i,j}\)为填满\(1~i\ ...

  3. 【bzoj2669】[cqoi2012]局部极小值 容斥原理+状压dp

    题目描述 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值. 给出所有局部极小值的位置,你的任 ...

  4. [BZOJ2669][CQOI2012]局部极小值:DP+容斥原理

    分析 题目要求有且只有一些位置是局部极小值.有的限制很好处理,但是只有嘛,嗯...... 考虑子集反演(话说这个其实已经算是超集反演了吧还叫子集反演是不是有点不太合适),枚举题目给出位置集合的所有超集 ...

  5. BZOJ 4042 Luogu P4757 [CERC2014]Parades (树形DP、状压DP)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4042 (Luogu) https://www.luogu.org/prob ...

  6. BZOJ 4417 Luogu P3990 [SHOI2013]超级跳马 (DP、矩阵乘法)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=4417 (luogu)https://www.luogu.org/prob ...

  7. BZOJ 3143 Luogu P3232 [HNOI2013]游走 (DP、高斯消元)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3143 (luogu) https://www.luogu.org/pro ...

  8. bzoj 1042: [HAOI2008]硬币购物【容斥原理+dp】

    当然是容斥啦. 用dp预处理出\( f[i] \),表示在\( i \)价格时不考虑限制的方案数,转移方程是\( f[i]+=f[i-c[j]] \),用状压枚举不满足的状态容斥一下即可. #incl ...

  9. BZOJ 3162 / Luogu P4895: 独钓寒江雪 树hash+DP

    题意 给出一棵无根树,求本质不同的独立集数模100000000710000000071000000007的值. n≤500000n\le 500000n≤500000 题解 如果是有根树就好做多了.然 ...

随机推荐

  1. 比反射更快!使用ASM获取class信息(ClassReader)

    比反射更快!使用ASM获取class信息(ClassReader) 通常我们想要在java运行时获取class的信息时,通常使用反射的方式来获取其中的属性,方法,注解等信息.通常是这样的: Class ...

  2. mybatis 基础(二) xml文件中的其他知识点

    mybatis xml文件中一些标签的使用 此标签主要用作 配置 "别名" 如果实体类与数据库中字段名在不区分大小写的情况下相同的话, 那就不需要配置resultMap,因为mys ...

  3. POJ - 1149 PIGS (建图思维+最大流)

    (点击查看原题) 题目分析 (以下均为 Edelweiss 大佬的思路,博主承认自己写不了这么好,但是学习的心促使我记录下这个好题的写法,所以代码是我写的) [题目大意] 有 M 个猪圈,每个猪圈里初 ...

  4. 批量操作checkbox

    通过post可获取选中的checkbox的value值,然后可以action到某一页面通过$_POST[]处理得到的checkbox的值,然后进行批量化增删改查等操作. // 关键性语句: <i ...

  5. 小白学习django第六站-http相关

    请求与相应 HttpRequest对象API def home(request): print('path:', request.path) print('mothod:', request.meth ...

  6. 最好用linux版QQ

    这个版本的qq是见过linux下做好用的qq,希望对大家有用; 安装简单,qq易用,不卡死,可以接收文件. 安装过程如下: git clone https://gitee.com/wszqkzqk/d ...

  7. Python验证码登录(Tesseract安装配置)

    1.安装py库:pytesseract,PIL pip install pytesseract pip install PILLOW 如果安装时,出现权限不足: pip install --user ...

  8. myBatis+Spring+SpringMVC框架面试题整理

    myBatis+Spring+SpringMVC框架面试题整理(一) 2018年09月06日 13:36:01 新新许愿树 阅读数 14034更多 分类专栏: SSM   版权声明:本文为博主原创文章 ...

  9. leetcode 1282. Group the People Given the Group Size They Belong To

    There are n people whose IDs go from 0 to n - 1 and each person belongs exactly to one group. Given ...

  10. RSA 加密长度计算公式

    The length of data that can be encrypted using RSA is determined primarily by the size of the key yo ...