上课讲的一道题,感觉也挺厉害的~正解是容斥 + 状压dp。首先我们容易发现一共可能的局部最小值数量是十分有限的,最多也只有 \(8\) 个。所以我们可以考虑状压。

  建立出状态 \(f[i][j]\) 表示我们从小到大往方格当中填数,填完前\(i\) 个数之后,局部最小值的填充状态为 \(j\) 的方案数。这样一共有两种转移 :

\(f[i][j] = f[i - 1][j] * (g[j] - ((i - 1) - |j|)) + \sum f[i][j']\)

  分别表示加入了一个局部最小值 / 其他位置的值。其中的 \(g[j]\) 表示在 \(j\) 的状态下可以放入的非局部最小值的个数。但这样做出来还是不够的——我们虽然保证了要求的位置上一定是局部最小值,但是其余的位置上也有可能是局部最小值,而这是不符合要求的。我们考虑用容斥来处理,用全集 - 至少有一个非局部最小值成为了局部最小值的方案数,+至少两个,-至少三个……

  每一个dfs出来的状态都用上面的方法dp加入到答案中去就可以了。

#include <bits/stdc++.h>
using namespace std;
#define maxn 400
#define maxm 500
#define int long long
#define mod 12345678
int n, m, N, tot, cnt, ans;
int Map[maxn][maxn], id[maxn][maxn];
int f[maxn][maxm], g[maxm], T;
int dx[] = {-, , , -, , -, , };
int dy[] = {-, -, -, , , , , }; struct node
{
int x, y;
}P[maxn]; void Up(int& x, int y) { x = (x + y) % mod; } int DP()
{
int K = ( << tot) - ;
for(int k = ; k <= K; k ++)
{
g[k] = ; int tem = k, len = ;
while(tem) len += (tem & ), tem >>= ;
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
{
int flag = ; if(Map[i][j]) continue;
for(int l = ; l < ; l ++)
{
int x = i + dx[l], y = j + dy[l];
if(Map[x][y] && !(( << (id[x][y] - )) & k))
{ flag = ; break; }
}
if(!flag) g[k] ++;
}
g[k] += len;
}
memset(f, , sizeof(f)); f[][] = ;
for(int i = ; i <= N; i ++)
for(int j = ; j <= K; j ++)
{
Up(f[i][j], f[i - ][j] * (g[j] - (i - )));
int tem = j, len = ;
while(tem) len ++, tem >>= ;
for(int k = ; k < len; k ++)
if(j & ( << k)) Up(f[i][j], f[i - ][j ^ ( << k)]);
}
return f[N][K];
} void DFS(int x, int y)
{
if(y > m) x += , y = ;
if(x > n)
{
if((tot - cnt) & ) ans = (ans - DP() + mod) % mod;
else ans = (ans + DP()) % mod;
return;
}
DFS(x, y + );
if(Map[x][y]) return;
for(int i = ; i < ; i ++)
if(Map[x + dx[i]][y + dy[i]]) return;
Map[x][y] = , P[++ tot].x = x, P[tot].y = y; id[x][y] = tot;
DFS(x, y + );
tot --, Map[x][y] = , id[x][y] = ;
} signed main()
{
scanf("%lld%lld", &n, &m); N = n * m;
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
{
char c; cin >> c;
if(c == 'X')
{
P[++ tot].x = i, P[tot].y = j;
Map[i][j] = , id[i][j] = tot;
}
}
cnt = tot;
for(int i = ; i <= tot; i ++)
{
T |= ( << (i - ));
for(int j = ; j < ; j ++)
if(Map[P[i].x + dx[j]][P[i].y + dy[j]])
{
printf("");
return ;
}
}
DFS(, );
printf("%lld\n", ans);
return ;
}

【题解】CQOI2012局部最小值的更多相关文章

  1. [BZOJ2669][CQOI2012]局部最小值(容斥+状压DP)

    发现最多有8个限制位置,可以以此为基础DP和容斥. $f_{i,j}=f_{i-1,j}\times (cnt_j-i+1)+\sum_{k\subset j} f_{i-1,k}$ $cnt_j$表 ...

  2. 【noip模拟】局部最小值

    TimeLimit: 1000ms               MemoryLimit: 256MB Description 有一个n行m列的整数矩阵,其中1到n×m之间的每个整数恰好出现一次.如果一 ...

  3. 关于过拟合、局部最小值、以及Poor Generalization的思考

    Poor Generalization 这可能是实际中遇到的最多问题. 比如FC网络为什么效果比CNN差那么多啊,是不是陷入局部最小值啊?是不是过拟合啊?是不是欠拟合啊? 在操场跑步的时候,又从SVM ...

  4. [nowCoder] 局部最小值位置

    定义局部最小的概念.arr长度为1时,arr[0]是局部最小.arr的长度为N(N>1)时,如果arr[0]<arr[1],那么arr[0]是局部最小:如果arr[N-1]<arr[ ...

  5. ●BZOJ 2669 [cqoi2012]局部极小值

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2669 题解: 容斥,DP,DFS 先看看 dp 部分:首先呢,X的个数不会超过 8个.个数很 ...

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

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

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

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

  8. bzoj2669 [cqoi2012]局部极小值 状压DP+容斥

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2669 题解 可以发现一个 \(4\times 7\) 的矩阵中,有局部最小值的点最多有 \(2 ...

  9. Mathematica 中 Minimize函数无法找到全局最小值时的解决方法

    一直使用Minimize来找到指定约束下的函数的最小值,最近发现在一个非线性函数中使用Minimize无法提供一个"全局"最小值(使用Mathematica只是用来验证算法的,所以 ...

随机推荐

  1. 12 动态语言 __slots__

    1. 动态语言的定义 动态编程语言 是 高级程序设计语言 的一个类别,在计算机科学领域已被广泛应用.它是一类 在运行时可以改变其结构的语言 :例如新的函数.对象.甚至代码可以被引进,已有的函数可以被删 ...

  2. MyBatis-MBG(MyBatis Generator)

    1.添加jar包 <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>m ...

  3. join_tab计算代价

    此路不通,还是需要按照顺序进行计算

  4. 2019年猪年海报PSD模板-第七部分

    14套精美猪年海报,免费猪年海报,下载地址:百度网盘,https://pan.baidu.com/s/1pE3X9AYirog1W8FSxbMiAQ              

  5. 「题目代码」P1044~P1048(Java)

    P1044 谭浩强C语言(第三版)习题5.8 import java.util.*; import java.io.*; import java.math.BigInteger; public cla ...

  6. SQL 怎么实现模糊查询?

    执行数据库查询时,有完整查询和模糊查询之分. 一般模糊语句格式如下: SELECT 字段 FROM 表 WHERE 某字段 LIKE 条件; 其中,关于条件,SQL提供了四种匹配模式: 一.%:表示零 ...

  7. Python 默认参数值

    Python 默认参数值,对于一些函数来说,你可能为希望使一些参数可选并使用默认的值,以避免用户不想为他们提供值的情况.默认参数值可以有效帮助解决这一情况.你可以通过在函数定义时附加一个赋值运算符(= ...

  8. TW实习日记:第20-21天

    为什么上周五没写呢,因为上周五一直在熟悉业务流程...根本不会写一些复杂的业务代码,因为没有业务流程图!!!在学校的上需求分析和UML建模课的时候,还有软件工程课的时候,想着这都什么鬼啊,听来干嘛,写 ...

  9. spring入门(Ioc的理解)

    spring对依赖的注入理解可以参考这篇:https://www.cnblogs.com/alltime/p/6729295.html 依赖注入和控制反转 传统的JavaEE程序中,直接在内部new一 ...

  10. parity注记词和地址

    remix skilled curled cobweb tactics koala bartender precinct energize exes ridden cohesive 0x00EeC52 ...