洛谷 P1763 状态压缩dp+容斥原理

时间:2022-09-20 18:49:44

(题目来自洛谷oj)

一天,maze决定对自己的一块n*m的土地进行修建。他希望这块土地共n*m个格子的高度分别是1,2,3,...,n*m-1,n*m。maze又希望能将这一些格子中的某一些拿来建蓄水池,即这个格子的高度应该比它周围8个格子的高度都小(超出土地范围的格子的高度算作无穷大)。现在,请你帮maze计算:他有多少种不同的修建土地的方案数?

(请你将方案数对12345678取模)

输入

输入第一行两个数字n,m。

接下来N行,每行M个字符,’.’表示普通格子,’X’表示蓄水池。

输出

仅一行,包含一个数字,为取模后的方案数。

一组输入输出大概长这样:

输入:                       输出:

3 5                        5851854
.X...
....X
X....

题意抽象:

    给定一个n*m个格子矩形,现在要将1,2,3....n*m个数字填入格子。

    问有且仅有指定格子满足条件p的方案数。

    条件p:该格子中的数比邻近8个格子中的数都小。

    数据范围1≤n≤4,m≤7。

首先数据范围挺小,最多28个格子,最多能不能有8个蓄水池。

于是想着搜一下。

但仔细想想发现还真是挺复杂的。

有几个关键点:

1.从小往大放数讨论方案数。这样的话如果“X”处已经放数了,那么它的旁边都可以放数了。否则它周围禁止放数。

2.不宜直接讨论当且仅当X处是蓄水池的方案数。讨论这样的方案数:保证题中所给的k个X处是蓄水池,但其他地方也可能是蓄水池的方案数。然后容斥。

这个容斥略有难想。

设目标状态S0中有k个蓄水池。设Ak为至少这k个X处是蓄水池的方案数。

先一次calc(S0)求出AS0。

然后要把其他地方还有蓄水池的方案数减掉。

于是往S0上加蓄水池(把某一个'.'变成‘X’),设加一个得到的状态S1.

由于加蓄水池的地方不同,会有很多种S1,我们记它们为S1,0...S1,i....S1,q

我们要减去的是AS1,0 ....AS1,i...AS1,q的并集的元素数目。

到这里容斥就很明显了。

更多具体细节在代码中注释:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int mo=;
int n,m,ans,tp;
char graph[][];
bool use[][];
int f[<<][];
int ax[],ay[];
void Input()
{
scanf("%d%d\n",&n,&m);
rep(i,,n-)
{
scanf("%s",graph[i]);
}
ans=;
}
bool inrange(int x,int y)
{
return x>=&&y>=&&x<n&&y<m;
}
int calc()
{
tp=;
memset(f,,sizeof(f));
f[][]=;
rep(i,,n-)
{
rep(j,,m-)
{
if(graph[i][j]=='X')
{
ax[tp]=i;ay[tp]=j;tp++;
}
}
}
for(int s=;s<(<<tp);++s)
{
memset(use,,sizeof(use));
rep(i,,tp-)
{
if(!(s&(<<i))) //如果这个X还没有放数
rep(dx,-,)
{
rep(dy,-,)
{
if(inrange(ax[i]+dx,ay[i]+dy)) use[ax[i]+dx][ay[i]+dy]=;
}
}
}
int cnt=; //cnt为可以随便放的位置的个数
rep(i,,n-)
{
rep(j,,m-) if(use[i][j]) ++cnt;
}
rep(i,,cnt) //数是从小往大放,只有X位置上已经放数了之后周围才能放数
{
if(f[s][i])
{
f[s][i+]=(f[s][i+]+f[s][i]*(cnt-i))%mo; //往无影响区域放数
rep(j,,tp-)
{
if(!(s&(<<j)))
{
f[s|(<<j)][i+]=(f[s|(<<j)][i+]+f[s][i])%mo; //往X上放数
}
}
}
}
}
return f[(<<tp)-][n*m];
}
void go(int x,int y,int k)
{ if(x>=n) ans=(ans+k*calc())%mo;
else if(y>=m) go(x+,,k);
else
{
go(x,y+,k);
bool ok=;
rep(dx,-,)
{
rep(dy,-,)
{
if(inrange(x+dx,y+dy)&&graph[x+dx][y+dy]=='X') ok=;
}
}
if(ok) //如果ok为0,这个点不能再设蓄水池了(注意此时(x,y)处必定不为题中所给蓄水池位置之一)
{
graph[x][y]='X';
go(x,y+,-k); //容斥。一条go路径得到的答案是'X'都满足是蓄水池但'.'处也可能是蓄水池的方案数
graph[x][y]='.';
}
}
}
int solve()
{
rep(i,,n-)
{
rep(j,,m-)
{
// printf("i=%d j=%d %c\n",i,j,graph[i][j]);
if(graph[i][j]=='X')
rep(dx,-,)
{
rep(dy,-,)
{
if((dx||dy)&&inrange(i+dx,j+dy)&&graph[i+dx][j+dy]=='X') return ;
}
}
}
}
ans=;
go(,,);
ans=(ans+mo)%mo;
return ans;
}
int main()
{
// freopen("in.txt","r",stdin);
Input();
printf("%d\n",solve());
return ;
}

洛谷 P1763 状态压缩dp+容斥原理的更多相关文章

  1. BZOJ1294 洛谷P2566 状态压缩DP 围豆豆

    传送门 题目描述 是不是平时在手机里玩吃豆豆游戏玩腻了呢?最近MOKIA手机上推出了一种新的围豆豆游戏,大家一起来试一试吧游戏的规则非常简单,在一个N×M的矩阵方格内分布着D颗豆子,每颗豆有不同的分值 ...

  2. 浅谈状态压缩DP

    浅谈状态压缩DP 本篇随笔简单讲解一下信息学奥林匹克竞赛中的状态压缩动态规划相关知识点.在算法竞赛中,状压\(DP\)是非常常见的动规类型.不仅如此,不仅是状压\(DP\),状压还是很多其他题目的处理 ...

  3. hdu4336 Card Collector 状态压缩dp

    Card Collector Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...

  4. hoj2662 状态压缩dp

    Pieces Assignment My Tags   (Edit)   Source : zhouguyue   Time limit : 1 sec   Memory limit : 64 M S ...

  5. POJ 3254 Corn Fields&lpar;状态压缩DP)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4739   Accepted: 2506 Descr ...

  6. &lbrack;知识点&rsqb;状态压缩DP

    // 此博文为迁移而来,写于2015年7月15日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w6jf.html 1.前 ...

  7. HDU-4529 郑厂长系列故事——N骑士问题 状态压缩DP

    题意:给定一个合法的八皇后棋盘,现在给定1-10个骑士,问这些骑士不能够相互攻击的拜访方式有多少种. 分析:一开始想着搜索写,发现该题和八皇后不同,八皇后每一行只能够摆放一个棋子,因此搜索收敛的很快, ...

  8. DP大作战—状态压缩dp

    题目描述 阿姆斯特朗回旋加速式阿姆斯特朗炮是一种非常厉害的武器,这种武器可以毁灭自身同行同列两个单位范围内的所有其他单位(其实就是十字型),听起来比红警里面的法国巨炮可是厉害多了.现在,零崎要在地图上 ...

  9. 状态压缩dp问题

    问题:Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Ev ...

随机推荐

  1. Spark笔记:复杂RDD的API的理解(上)

    本篇接着讲解RDD的API,讲解那些不是很容易理解的API,同时本篇文章还将展示如何将外部的函数引入到RDD的API里使用,最后通过对RDD的API深入学习,我们还讲讲一些和RDD开发相关的scala ...

  2. MySQL数据库初识(二)

    8. 向数据表中插入数据记录(INSERT): 向数据表中插入数据记录有两种方法: 基本语法1:INSERT INTO 数据表 (字段名1,字段名2,字段名3……字段名n) VALUES (数据值1, ...

  3. Java 数组 可变长参数 实例

    可以把类型相同但个数可变的参数传递给方法,方法中的参数声明如下: typeName...parameterName (类型名...参数名) 在方法声明中,指定类型后紧跟着省略号...,只能给方法指定一 ...

  4. &lbrack;leetcode&rsqb;&lowbar;Path Sum I &amp&semi;&amp&semi; II

    都是考查DFS.经典回溯算法,问题在于我对该类型的代码不熟悉,目前以参考别人的代码,然后加上自己的实现为主,通过类似的题目加强理解. 一.给定一棵二叉树,判断是否存在从root到leaf的路径和等于给 ...

  5. 先贴出代码C&plus;&plus; 中的单例模式

    先贴出代码,代码后面是讲解 自己编写的单例模式: #include <iostream> #include <stdio.h> #include <string> ...

  6. Asp&period;net中防止用户多次登录的方法

    在web开发时,有的系统要求同一个用户在同一时间只能登录一次,也就是如果一个用户已经登录了,在退出之前如果再次登录的话需要报错. 常见的处理方法是,在用户登录时,判断此用户是否已经在Applicati ...

  7. http请求 405错误 方法不被允许 &lpar;Method not allowed&rpar;

    由于自己疏忽,导致请求错误405,然后前端数据传输没错,百度大都说跟post提交方式有关,改成get还是报错,检查才知道,controller中忘记写@requestMapping("/XX ...

  8. Socket网络编程基本介绍

    一,socket的起源 socket一词的起源 在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的, 撰写者为Stephen Carr.Steve Crocker和Vi ...

  9. 2016-2017 ACM-ICPC Northeastern European Regional Contest Problem E&period; Expect to Wait

    题目来源:http://codeforces.com/group/aUVPeyEnI2/contest/229509 时间限制:2s 空间限制:512MB 题目大意: 在一个车站中有若干人在队列中等待 ...

  10. ReactNative之坑:停在gradle一直出点

    问题: 初次安装好React Native 环境后,运行项目,会停留在下载 gradle 的界面一直出点 原因: 下载gradle一直不成功 解决方案: 可以根据提示的版本信息,手动下载,放在目录中, ...