题目链接

(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. mongodb 添加用户

    use admindb.createUser({ user:"admin", pwd:"abc123456", roles:[{role:"root& ...

  2. 基于FCN的图像语义分割

    语义图像分割的目标在于标记图片中每一个像素,并将每一个像素与其表示的类别对应起来.因为会预测图像中的每一个像素,所以一般将这样的任务称为密集预测.(相对地,实例分割模型是另一种不同的模型,该模型可以区 ...

  3. Java Web开发技术教程入门-JavaBean组件与Servlet

    补更:阅战阅勇第7/8/9Days笔记 昨天我们了解了JDBC技术的一些日常操作,对于数据库而言,不仅仅的只有"增,删,改,查".博主觉得最重要的是SQL语句的优化,一个" ...

  4. 小程序之textarea层级最高问题

    1.textarea位于底部固定定位按钮下方,会导致点击底部按钮,textarea获取到焦点. 解决方法如下 view与textarea之间在聚焦和失去焦点进行切换 cursor-spacing是te ...

  5. performance面板使用,以及解决动画卡顿

    https://googlechrome.github.io/devtools-samples/jank//    官方案例 https://juejin.im/post/5b65105f518825 ...

  6. N4_75条语法

    1. コ/ソ/ア/ド体系 -(こ.そ.あ.ど)れ/-(こ.そ.あ.ど)の A:-(こ.そ.あ.ど)れ 接续: 指示代词和场所代词,分近称.中称.远称.疑问称. 意思: 这个,那个,那个,哪个 例:これ ...

  7. TKmybatis和mybatisplus哪个好用

    文档连接 :http://baomidou.oschina.io/mybatis-plus-doc/#/?id=%E7%AE%80%E4%BB%8B https://gitee.com/hengboy ...

  8. IT经理工作职责

    IT经理工作职责:     1. 管理公司信息技术以及计算机系统.   2. 确保公司信息技术是可访问的并且配备了现有的可用的硬件和软件.   3. 监控并且维护公司信息技术并确保能够得到最大化的使用 ...

  9. linux上搭建单机版hadoop和spark

    依赖的安装包 首先hadoop和spark肯定是必须的,而hadoop是用java编写的,spark是由Scala编写的,所以还需要安装jdk和scala. 大数据第三方组件我们统统都安装在/opt目 ...

  10. LCD 原理和移植总结【转】

    转自:http://blog.chinaunix.net/uid-22915173-id-329617.html Framebuffer:是linux的framebuffer驱动在内存开辟的一块显存, ...