●BZOJ 2669 [cqoi2012]局部极小值
题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=2669
题解:
容斥,DP,DFS
先看看 dp 部分:
首先呢,X的个数不会超过 8个。
个数很少,所以考虑状压,把需要填 X的那几个位置状压为二进制10表示对应的那个X位置是否已经填数。
同时填的数互不重复,考虑从小填到大。
令 cnt[S] 表示除了不在集合 S 里的 X 位置及其周围的位置,剩下的位置个数。
定义 dp[i][S]表示从小到大填数填完了i这个数,且已经填了的 S 这个集合里的 X 位置的方案数。
转移:依次去填数 1~N*M,每次有两种选择:
1).把这个数填在 某个 X 位置(枚举一个 k表示第 k个 X 位置填当前数)
dp[i][S]+=dp[i-1][S^(1<<(k-1))]
2).把这个数填在非 X 位置,那么填的位置有 cnt[S]-(i-1) 种。
dp[i][s]+=dp[i-1][s]*(cnt[s]-(i-1)) (好好理解一下这个转移)
这样 dp 可以保证那些给出的 X 位置一定是局部最小值,
因为第二种转移的填数位置都不能填在还没有填数的 X 位置的周围。
所以就完了么?
当然还没有,尽管我们保证了给出的 X 位置一定是局部最小值,
但是没有保证非 X位置一定不是非局部最小值。即,求出来的 dp[N*M][all_S(全集)]的意思是至少all_S集合里的 X位置为局部最小值的方案数。
所以容斥如下:
ANS = 至少多填了0个局部最小值的方案数(dp[N*M][all_S])
-至少多填了1个局部最小值的方案数
+至少多填了2个局部最小值的方案数
-....+ ....
这些用于容斥的方案数的求法:
DFS 搜索出哪些非 X 位置还可以改为 X ,
然后对于每一种新的填法,去跑一遍上述的dp即可求得对应的方案数。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define _ % mod
#define filein(x) freopen(#x".in","r",stdin);
#define fileout(x) freopen(#x".out","w",stdout);
using namespace std;
const int mv[9][2]={{0,0},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
const int mod=12345678;
char mp[10][10];
int N,M,ANS;
int solve(){
static bool vis[10][10];
static int dp[30][1<<8],cnt[1<<8],x[10],y[10],tot,tmp;
tot=0; memset(dp,0,sizeof(dp));
for(int i=1;i<=N;i++)
for(int j=1;j<=M;j++) if(mp[i][j]=='X')
tot++,x[tot]=i,y[tot]=j;
for(int s=0;s<1<<tot;s++){
tmp=0; memset(vis,0,sizeof(vis));
for(int i=1;i<=tot;i++) if(!(s&(1<<(i-1))))
for(int k=0;k<9;k++)
vis[x[i]+mv[k][0]][y[i]+mv[k][1]]=1;
for(int i=1;i<=N;i++)
for(int j=1;j<=M;j++)
if(!vis[i][j]) tmp++;
cnt[s]=tmp;
}
dp[0][0]=1;
for(int i=1;i<=N*M;i++)
for(int s=0;s<1<<tot;s++){
dp[i][s]=(1ll*dp[i][s]+1ll*dp[i-1][s]*max(cnt[s]-(i-1),0)_)_;
for(int k=1;k<=tot;k++) if(s&(1<<(k-1)))
dp[i][s]=(1ll*dp[i][s]+dp[i-1][s^(1<<(k-1))])_;
}
return dp[N*M][(1<<tot)-1];
}
void dfs(int x,int y,int t){
if(y==M+1){dfs(x+1,1,t);return;}
if(x==N+1){
int tmp=solve();
if(t&1) tmp=(-1ll*tmp+mod)_;
ANS=((1ll*ANS+tmp)_+mod)_;
return;
}
dfs(x,y+1,t);
bool fg=1;
for(int k=0;k<9;k++)
if(mp[x+mv[k][0]][y+mv[k][1]]=='X') fg=0;
if(fg){
mp[x][y]='X';
dfs(x,y+1,t+1);
mp[x][y]='.';
}
}
int main()
{
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++)
scanf("%s",mp[i]+1);
dfs(1,1,0);
printf("%d",ANS);
return 0;
}
●BZOJ 2669 [cqoi2012]局部极小值的更多相关文章
- bzoj 2669 [cqoi2012]局部极小值 DP+容斥
2669: [cqoi2012]局部极小值 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 838 Solved: 444[Submit][Status ...
- BZOJ 2669 CQOI2012 局部极小值 状压dp+容斥原理
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2669 题意概述:实际上原题意很简洁了我就不写了吧.... 二话不说先观察一下性质,首先棋盘 ...
- 【BZOJ 2669】 2669: [cqoi2012]局部极小值 (状压DP+容斥原理)
2669: [cqoi2012]局部极小值 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 667 Solved: 350 Description 有一 ...
- 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之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点) ...
- P3160 [CQOI2012]局部极小值
题目 P3160 [CQOI2012]局部极小值 一眼就是状压,接下来就不知道了\(qwq\) 做法 我们能手玩出局部小值最多差不多是\(8,9\)个的样子,\(dp_{i,j}\)为填满\(1~i\ ...
- 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\)好题. 由于需要保证某些位置比周围都要小,那么我们可以从小到大把每个数依次填入,保证每个局部极小值填入之前周围都不能填,就只需要在加入的时候计数了. 由于局部 ...
随机推荐
- 【iOS】Swift if let 和 if var
if let unwrappedOptional = postDict { print("The optional has a value! It's \(unwrappedOptional ...
- LR回放https协议脚本失败: 错误 -27778: 在尝试与主机“www.baidu.com”connect 时发生 SSL 协议错误
今天用LR录制脚本协议为https协议,回放脚本时出现报错: Action.c(14): 错误 -27778: 在尝试与主机"www.baidu.com"connect 时发生 S ...
- Java中RuntimeException和Exception的区别
[TOC] 1. 引入RuntimeException public class RuntimeException { public static void main(String[] args) { ...
- nyoj 背包问题
背包问题 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w< ...
- zookeeper安装及环境变量设置
下载 首先去官网下载(自行选择版本):http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.11/然后执行tar -zxvf解压 对于后台安装 ...
- python之路--day8---day9--两日内容
一.不使用函数的问题 1,代码的组织结构不清晰,可读性差 2,遇到重复的功能只能重复编写实现代码,代码冗余 3,功能需要扩展时,需要找出所有实现该功能的地方修改,无法统一管理且维护难度极大 二.函数是 ...
- JAVA_SE基础——37.main方法的详解
主函数 大家都会写吧. 大家一直都不知道为何这样设计,这样设计有什么好处呢? 白话解释: main函数的修饰符是public: 公共的 为何不用private 等等的修饰符 而规定只用public呢? ...
- linux系统命令学习系列-例行任务管理at命令
先来复习一下上节内容: 切换用户身份命令su 以root身份执行操作命令sudo 作业:给user1配置sudo权限,不用密码,可执行useradd命令 在/etc/sudoers文件中添加如下配置项 ...
- Python内置函数(22)——list
英文文档: class list([iterable]) Rather than being a function, list is actually a mutable sequence type, ...
- Apollo单向SSL认证(1)
参考链接:https://www.cnblogs.com/benwu/articles/4891758.html keytool -genkey -alias mybroker -keyalg RSA ...