bzoj2669-局部极小值
题意
有一个 \(n\times m\) 的矩阵,其中每个数都是 \([1,n\times m]\) 中的一个,不会重复。有一些地方的值比周围的8个位置都小(如果有的话)。给出这些位置,求这样的矩阵有多少个。
\(n\le 4,m\le 7\) 。
分析
一个很关键的信息是局部极小值的点最多只有8个,以及每个数都不会重复。
这种有大小关系的填数问题,我们可以考虑从小到大填每个数。如果能够确定当前限制点的填写情况(是否填了),那么我们就能知道当前的决策有多少个可行位置。因为我们是从小到大填每个数,所以每个数的每个位置都是一种方案。
状态压缩当前限制的填写情况,预处理在一种填写状态下有多少个位置能填,我们就可以通过分当前这个数填在限制位置还是非限制位置进行dp。
然而会有一些不合法的情况,原因是没有限制的位置我们随便乱填之后可能会出现局部极小值,所以我们要把这些情况减掉。所以使用容斥原理减少限制——保证有某一些为局部极小值,其他不管,进行容斥。我们进行dfs,有哪些位置保证为局部极小值。
单次dp的复杂度为 \((2^Xnm)\) ,dfs剪枝能够通过。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long giant;
const int xx[]={-1,-1,-1,0,1,1,1,0};
const int yy[]={-1,0,1,1,1,0,-1,-1};
const int maxn=5;
const int maxm=8;
const int maxx=8;
const int maxs=1<<maxx;
const int q=12345678;
inline int Plus(int x,int y) {return ((giant)x+(giant)y)%q;}
inline int Multi(int x,int y) {return (giant)x*y%q;}
int n,m,ans=0,p[maxx][2],cnt[maxs],f[maxn*maxm][maxs],nm,ord=0;
bool a[maxn][maxm],mp[maxn][maxm];
inline int nxtx(int x,int y) {return x+(y==m);}
inline int nxty(int x,int y) {return y==m?1:y+1;}
void dp() {
int g=0,s;
for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) if (a[i][j]) {
for (int k=0;k<8;++k) {
int x=i+xx[k],y=j+yy[k];
if (x>0 && y>0 && x<=n && y<=m && a[x][y]) return;
}
p[g][0]=i,p[g][1]=j;
++g;
}
s=1<<g;
memset(cnt,0,sizeof cnt);
for (int j=0;j<s;++j) {
memset(mp,0,sizeof mp);
for (int i=0;i<g;++i) if (!((j>>i)&1)) {
mp[p[i][0]][p[i][1]]|=true;
for (int k=0;k<8;++k) {
int x=p[i][0]+xx[k],y=p[i][1]+yy[k];
if (x>0 && y>0 && x<=n && y<=m) mp[x][y]|=true;
}
}
for (int i=1;i<=n;++i) for (int k=1;k<=m;++k) cnt[j]+=(!mp[i][k]);
}
memset(f,0,sizeof f);
f[0][0]=1;
for (int i=1;i<=nm;++i) for (int j=0;j<s;++j) {
if (cnt[j]>i-1) f[i][j]=Multi(f[i-1][j],cnt[j]-i+1);
for (int k=0;k<g;++k) if ((j>>k)&1) f[i][j]=Plus(f[i][j],f[i-1][j^(1<<k)]);
}
ans=Plus(ans,(g-ord)&1?q-f[nm][s-1]:f[nm][s-1]);
}
void dfs(int x,int y) {
if (x>n) {
dp();
return;
}
dfs(n+1,1);
for (int i=nxtx(x,y),j=nxty(x,y);i<=n;x=i,y=j,i=nxtx(x,y),j=nxty(x,y)) if (!a[i][j]) {
bool flag=true;
for (int k=0;k<8;++k) {
int x=i+xx[k],y=j+yy[k];
if (x>0 && y>0 && x<=n && y<=m && a[x][y]) {
flag=false;
break;
}
}
if (!flag) continue;
a[i][j]=true;
dfs(i,j);
a[i][j]=false;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
scanf("%d%d",&n,&m),nm=n*m;
for (int i=1;i<=n;++i) {
static char s[maxm+2];
scanf("%s",s+1);
for (int j=1;j<=m;++j) if (s[j]=='X') a[i][j]=true,++ord;
}
dfs(1,0);
printf("%d\n",ans);
return 0;
}
bzoj2669-局部极小值的更多相关文章
- BZOJ2669 [cqoi2012]局部极小值 状压DP 容斥原理
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2669 题意概括 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所 ...
- [BZOJ2669] [cqoi2012]局部极小值
[BZOJ2669] [cqoi2012]局部极小值 Description 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点) ...
- 【BZOJ-2669】局部极小值 状压DP + 容斥原理
2669: [cqoi2012]局部极小值 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 561 Solved: 293[Submit][Status ...
- bzoj2669[cqoi2012]局部极小值 容斥+状压dp
2669: [cqoi2012]局部极小值 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 774 Solved: 411[Submit][Status ...
- 【bzoj2669】 cqoi2012—局部极小值
http://www.lydsy.com/JudgeOnline/problem.php?id=2669 (题目链接) 题意 给出一个$n*m$的整数矩阵,其中$[1,nm]$中的整数每个出现一次,有 ...
- 【bzoj2669】[cqoi2012]局部极小值 容斥原理+状压dp
题目描述 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值. 给出所有局部极小值的位置,你的任 ...
- [BZOJ2669][CQOI2012]局部极小值:DP+容斥原理
分析 题目要求有且只有一些位置是局部极小值.有的限制很好处理,但是只有嘛,嗯...... 考虑子集反演(话说这个其实已经算是超集反演了吧还叫子集反演是不是有点不太合适),枚举题目给出位置集合的所有超集 ...
- bzoj2669 [cqoi2012]局部极小值 状压DP+容斥
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2669 题解 可以发现一个 \(4\times 7\) 的矩阵中,有局部最小值的点最多有 \(2 ...
- bzoj 2669 [cqoi2012]局部极小值 DP+容斥
2669: [cqoi2012]局部极小值 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 838 Solved: 444[Submit][Status ...
- 【CQOI2012】局部极小值
[CQOI2012]局部极小值 Description 有一个\(n\)行\(m\)列的整数矩阵,其中\(1\)到\(nm\)之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或 ...
随机推荐
- 关于网易云验证码V1.0版本的服务介绍
服务介绍 易盾验证码是一个用于区分人和机器的通用验证码组件.传统的字符型验证码由于存在破解率高,用户体验不友好等问题,已不适用于现今的互联网环境.易盾验证码抛弃了传统字符型验证码展示-填写字符-比对答 ...
- Hibernate三种状态的区分,以及save,update,saveOrUpdate,merge等的使用
Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached).处于持久态的对象也称为PO(Persistence Object ...
- 二、利用EnterpriseFrameWork快速开发Web系统(B/S)
EnterpriseFrameWork框架实例源代码下载: 实例下载 本章通过一个开发实例来讲解Web系统的开发经过,以及会碰到的一些问题.实例功能就是业务系统中最常见的增.删.改.查来演示,用一个界 ...
- unittest,requests——接口测试脚本及报告
用unittest管理两个利用requests模块,做百度搜索的简单接口测试用例,之后自动输出报告 # encoding=utf-8import requests,unittest,HTMLTestR ...
- Vue学习计划基础笔记(四) - 事件处理
事件处理 目标: 熟练掌握事件监听的方式,熟悉事件处理方式以及各类事件修饰符 理解在html中监听事件的意义 监听事件(v-on) 类似普通的on,例如v-on:click或@click就相当于普通的 ...
- python程序设计——面向对象程序设计:属性
python 3.x 的属性 可以将属性设置为 可读,可修改,可删除 # 只读属性,不允许修改和删除 class Test: def __init__(self,value): self.__valu ...
- Spring学习(2):面向接口编程思想
一. 引言 Spring核心的IOC的实体用了面向接口编程思想,所以有必要了解下.简单来说的话,Spring就是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架. 接口的定义的概念:泛指实 ...
- python-redis集合模式
无序集合SADD set集合是直接去重的,只会输出 xiao hehe sadd names3 xiao xiao hehe hehe 获取集合 names3的所有值,集合不能用切片形式获取值, ...
- 【MySQL 数据库】MySQL目录
目录 [第一章]MySQL数据概述 [第二章]MySQL数据库基于Centos7.3-部署 [MySQL解惑笔记]Centos7下卸载彻底MySQL数据库 [MySQL解惑笔记]忘记MySQL数据库密 ...
- hdu - 6282,2018CCPC湖南全国邀请赛G题,字符串,规律
HDU – 6282 http://acm.hdu.edu.cn/showproblem.php?pid=6282 by Hzu_Tested 题意:给出两个字符串S和T,只由a,b,c三种字符组成( ...