BZOJ 2669 Luogu P3160 [CQOI2012]局部极小值 (容斥原理、DP)
题目链接
(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)的更多相关文章
- P3160 [CQOI2012]局部极小值 题解(状压DP+容斥)
题目链接 P3160 [CQOI2012]局部极小值 双倍经验,双倍快乐 解题思路 存下来每个坑(极小值点)的位置,以这个序号进行状态压缩. 显然,\(4*7\)的数据范围让极小值点在8个以内(以下示 ...
- P3160 [CQOI2012]局部极小值
题目 P3160 [CQOI2012]局部极小值 一眼就是状压,接下来就不知道了\(qwq\) 做法 我们能手玩出局部小值最多差不多是\(8,9\)个的样子,\(dp_{i,j}\)为填满\(1~i\ ...
- 【bzoj2669】[cqoi2012]局部极小值 容斥原理+状压dp
题目描述 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值. 给出所有局部极小值的位置,你的任 ...
- [BZOJ2669][CQOI2012]局部极小值:DP+容斥原理
分析 题目要求有且只有一些位置是局部极小值.有的限制很好处理,但是只有嘛,嗯...... 考虑子集反演(话说这个其实已经算是超集反演了吧还叫子集反演是不是有点不太合适),枚举题目给出位置集合的所有超集 ...
- BZOJ 4042 Luogu P4757 [CERC2014]Parades (树形DP、状压DP)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4042 (Luogu) https://www.luogu.org/prob ...
- BZOJ 4417 Luogu P3990 [SHOI2013]超级跳马 (DP、矩阵乘法)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=4417 (luogu)https://www.luogu.org/prob ...
- BZOJ 3143 Luogu P3232 [HNOI2013]游走 (DP、高斯消元)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3143 (luogu) https://www.luogu.org/pro ...
- bzoj 1042: [HAOI2008]硬币购物【容斥原理+dp】
当然是容斥啦. 用dp预处理出\( f[i] \),表示在\( i \)价格时不考虑限制的方案数,转移方程是\( f[i]+=f[i-c[j]] \),用状压枚举不满足的状态容斥一下即可. #incl ...
- BZOJ 3162 / Luogu P4895: 独钓寒江雪 树hash+DP
题意 给出一棵无根树,求本质不同的独立集数模100000000710000000071000000007的值. n≤500000n\le 500000n≤500000 题解 如果是有根树就好做多了.然 ...
随机推荐
- linux yum安装过程终止方法
//中断当前的安装显示 ctrl+z //查找当前yum相关的进程 ps -ef | grep yum //杀掉进程 进程号(pid)
- Mysql-Sqlalchemy-ORM框架
import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declar ...
- 百度地图 echarts tooltip属性 经纬度坐标不显示
中国地图.散点图结合点击后显示当前城市数量 不显示经纬度坐标 echarts.appMap = function (id, opt) { // 实例 var chart = this.init(doc ...
- HTTP/HTTPS协议 & GraphQL(非RESTFUL方式)
HTTP访问控制-跨域资源共享(CORS) 缓存管理 HTTP VS HTTPS架构 TLS协议 HTTPS会话劫持 基于HTTP协议的服务器消息机制 1. Longpoll 2. SSE 3. We ...
- Web前端开发解耦1
在网站建设的工作中,Web前端工程师占据着非常重要的位置,好的前端工程师保证了良好的网站优化以及友好的用户体验.今天佚站互联主要分享一下对于Web前端开发规范的一些见解. 学过面向对象编程的朋友应该都 ...
- 使用Ant打包工具
由于使用java,javac,jar等工具进行编译打包,即繁琐低效又容易出错,因此Ant出现了.Ant的出现就是专门为了打包编译java代码的,使用之前得稍微学一下.Ant的运行起来主要是依靠配置文件 ...
- 华为服务器XH628配置软RAID
1. 硬RAID 1.1. 配置准备 本机型号为华为XH628,配有两块400GSSD,12块1.2TSAS盘.其中2块SSD做RAID1为系统盘,12块SAS盘做RAID5, ...
- 完美解决Mysql的Access denied for user 'root'@'%的'问题
背景:mysql5.6 root已授权所有数据库,执行过下面的语句 grant all privileges on *.* to 'root'@'%' identified by 'root' 当使用 ...
- redis3.2 源码安装
wget http://download.redis.io/releases/redis-3.2.3.tar.gz tar -zxvf redis-.tar.gz cd redis make & ...
- libusb读写
https://blog.csdn.net/u012247418/article/details/83684980 https://github.com/crazybaoli/libusb-test ...