题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=2669

题解

可以发现一个 \(4\times 7\) 的矩阵中,有局部最小值的点最多有 \(2\times 4 = 8\) 个,所以我们可以状压一下每个局部最小值的位置有没有被选。

从小到大填入每一个格子,那么如果一个点的周围有没有被填上的局部最小值,那么这个格子不可以被填。所以预处理一下每种状态下可以自由填多少格子,然后如果状态保持不变的话,就可以这样转移。

如果状态变化,就是说填了一个局部最小值的话,那么久直接加上当前状态的答案就可以了。


但是这样会有问题:被自由填的位置,可能会出现多余的局部最小值,也就说不该是局部最小值的地方出现了局部最小值——那么就直接容斥一下就好了,直接搜索一个各种合法状态,都 DP 一下。

这个 DP 的复杂度很显然是 \(O(nm \cdot 8 \cdot 2^8)\),但是搜索我就不太会算了。总之可以轻松的过掉。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int N = 4 * 7 + 7;
const int M = (1 << 8) + 7;
const int dx[] = {0, 1, 1, 1, 0, -1, -1, -1}, dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
const int P = 12345678; int n, m, pcnt, cnt, S, ans;
pii p[N];
int wy[M], dp[N][M];
char a[N][N], b[N][N], mk[5][8]; inline int smod(int x) { return x >= P ? x - P : x; }
inline void sadd(int &x, const int &y) { x += y; x >= P ? x -= P : x; }
inline int fpow(int x, int y) {
int ans = 1;
for (; y; y >>= 1, x = (ll)x * x % P) if (y & 1) ans = (ll)ans * x % P;
return ans;
} inline void ycl() {
S = (1 << cnt) - 1;
memset(wy, 0, sizeof(wy));
for (int s = 0; s <= S; ++s) {
int &ans = wy[s];
memset(mk, 0, sizeof(mk));
for (int i = 1; i <= cnt; ++i) if (!((s >> (i - 1)) & 1)) {
int x = p[i].fi, y = p[i].se;
mk[x][y] = 1;
for (int i = 0; i < 9; ++i) {
int px = x + dx[i], py = y + dy[i];
if (px < 1 || px > n || py < 1 || py > m) continue;
mk[px][py] = 1;
}
}
for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) if (!mk[i][j]) ++ans;
}
} inline void DP() {
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (int i = 0; i < n * m; ++i) {
for (int s = 0; s <= S; ++s) {
sadd(dp[i + 1][s], (ll)dp[i][s] * (wy[s] - i) % P);
for (int j = 1; j <= cnt; ++j) if (!((s >> (j - 1)) & 1))
sadd(dp[i + 1][s ^ (1 << (j - 1))], dp[i][s]);
}
}
} inline void calc() {
cnt = 0;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) if (b[i][j]) p[++cnt] = pii(i, j);
ycl();
DP();
if ((cnt - pcnt) & 1) sadd(ans, P - dp[n * m][S]);
else sadd(ans, dp[n * m][S]);
} inline void dfs(int x, int y) {
if (x == n + 1) return calc();
if (y == m) dfs(x + 1, 1); else dfs(x, y + 1);
int flag = 1;
for (int i = 0; i < 9; ++i) {
int px = x + dx[i], py = y + dy[i];
if (px < 1 || px > n || py < 1 || py > m) continue;
if (b[px][py]) { flag = 0; break; }
}
if (a[x][y] || !flag) return;
b[x][y] = 1;
if (y == m) dfs(x + 1, 1); else dfs(x, y + 1);
b[x][y] = 0;
} inline void work() {
for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) if (a[i][j])
for (int k = 1; k <= n; ++k) for (int l = 1; l <= n; ++l) if (a[k][l])
if (abs(i - k) <= 1 && abs(j - l) <= 1 && (i != k || j != l)) return (void)puts("0");
memcpy(b, a, sizeof(a));
dfs(1, 1);
printf("%d\n", ans);
} inline void init() {
read(n), read(m);
for (int i = 1; i <= n; ++i) {
scanf("%s", a[i] + 1);
for (int j = 1; j <= m; ++j) a[i][j] = a[i][j] == 'X', pcnt += a[i][j];
}
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

bzoj2669 [cqoi2012]局部极小值 状压DP+容斥的更多相关文章

  1. BZOJ2669 [cqoi2012]局部极小值 状压DP 容斥原理

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2669 题意概括 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所 ...

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

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

  3. codeforces 342D Xenia and Dominoes(状压dp+容斥)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud D. Xenia and Dominoes Xenia likes puzzles ...

  4. BZOJ 2669 CQOI2012 局部极小值 状压dp+容斥原理

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2669 题意概述:实际上原题意很简洁了我就不写了吧.... 二话不说先观察一下性质,首先棋盘 ...

  5. 一本通 1783 矩阵填数 状压dp 容斥 计数

    LINK:矩阵填数 刚看到题目的时候感觉是无从下手的. 可以看到有n<=2的点 两个矩形. 如果只有一个矩形 矩形外的方案数容易计算考虑 矩形内的 必须要存在x这个最大值 且所有值<=x. ...

  6. 【BZOJ-2669】局部极小值 状压DP + 容斥原理

    2669: [cqoi2012]局部极小值 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 561  Solved: 293[Submit][Status ...

  7. HDU 5838 (状压DP+容斥)

    Problem Mountain 题目大意 给定一张n*m的地图,由 . 和 X 组成.要求给每个点一个1~n*m的数字(每个点不同),使得编号为X的点小于其周围的点,编号为.的点至少大于一个其周围的 ...

  8. [清华集训2015 Day1]主旋律-[状压dp+容斥]

    Description Solution f[i]表示状态i所代表的点构成的强连通图方案数. g[i]表示状态i所代表的的点形成奇数个强连通图的方案数-偶数个强连通图的方案数. g是用来容斥的. 先用 ...

  9. NOIp模拟赛 巨神兵(状压DP 容斥)

    \(Description\) 给定\(n\)个点\(m\)条边的有向图,求有多少个边集的子集,构成的图没有环. \(n\leq17\). \(Solution\) 问题也等价于,用不同的边集构造DA ...

随机推荐

  1. BZOJ 1096: [ZJOI2007]仓库建设 动态规划 + 斜率优化

      #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) #defi ...

  2. 虚拟机CentOS7安装docker并搭建Gitlab私服

    一.下载安装虚拟机和CentOS7系统 这些流程比较简单不会有什么坑,这里不再阐述 二.安装docker 1.Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验 ...

  3. vue双向数据绑定对于数组和新增对象属性不能监听的解决办法

    出现数组不能按照索引进行跟新的原因是处于性能考虑的,但是整体数组的增加删除是可以监听到的:对于对象新增属性不能监听是因为没有在生成vue实例时候放进watcher收集依赖. 首先我们先来了解vue数据 ...

  4. js请求解析xml

    xml数据 <?xml version="1.0" encoding="utf-8"?> <table> <node name=& ...

  5. php常见五种设计模式

    php面向对象基础知识 请点击查看 一.常见的设计模式主要有23种,根据使用目标的不同可以分为以下三大类:创建设计模式.结构设计模式.行为模式创建设计模式: (5种)用于创建对象时的设计模式.初始化对 ...

  6. MySQL部分索引

    部分索引 char/varchar2太长,全部做索引的话,效率低,浪费存储空间 select avg(length(username)) from 索引统计: show index from tabl ...

  7. HDU 1269 迷宫城堡 (Kosaraju)

    题目链接:HDU 1269 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000), ...

  8. MySQL 查询语句--------------进阶8:分页查询

    #进阶8:分页查询 /* 应用场景:要显示的数据,一页显示不全,需要分页提交sql请求 语法: select 查询列表 from 表 [join type] join 表2 on 连接条件 [wher ...

  9. 《JAVA设计模式》之备忘录模式(Memento)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述备忘录(Memento)模式的: 备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式. 备忘录 ...

  10. Netty之揭开BootStrap 的神秘面纱

    客户端BootStrap: Bootstrap 是Netty 提供的一个便利的工厂类, 我们可以通过它来完成Netty 的客户端或服务器端的Netty 初始化.下面我先来看一个例子, 从客户端和服务器 ...