【GDKOI 2016】地图 map 类插头DP
Description
对于一个n*m的地图,每个格子有五种可能:平地,障碍物,出口,入口和神器。一个有效的地图必须满足下列条件:
1.入口,出口和神器都有且仅出现一次,并且不在同一个格子内。
2.入口,出口和神器两两都是连通的。
连通性判断为四连通。
现在给出一个n*m的地图,其中一些格子的状态已经确定,另一些格子的状态未确定。
问当所有的格子状态确定之后,有多少种情况使得该地图是一个有效的地图?输出结构为答案模1e9+7。
Input
第一行输入两个整数n和m,意义如题目所示。接下来n行,每行m个字符:
字符'.'表示平地
字符'#'表示障碍物
字符'?'表示未确定
字符'S'表示入口
字符'X'表示神器
字符'E'表示出口
Output
一行,表示方案数
Sample Input
2 3
S#E
???
Sample Output
3
HINT
对于30%的数据,?数量小于10
对于100%的数据,1<=n<=7,1<=m<=7
Solution
这是一道类插头DP的题目,做法与插头DP类似。
对于'?',我们可以枚举情况;而对于其他已经确定了的状态,可以直接按格DP。
状态只需记录格子所在的连通块,并在最后记录入口,出口和神器所在的连通块,HASH存。
Code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm> using namespace std; #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define DWN(i, a, b) for (int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define mset(a, b) memset(a, b, sizeof(a))
typedef long long LL;
const int MAXD = , HASH = , STATE = , MOD = 1e9+;
int n, m, code[MAXD], ch[MAXD], x[], y[];
char maze[MAXD][MAXD], sp[] = {'S', 'X', 'E', '.', '#'}; void add(LL &x, LL y) { x += y; if (x >= MOD) x -= MOD; } struct HASHMAP
{
int head[HASH], nxt[STATE], siz; LL state[STATE], f[STATE];
void clear() { siz = , mset(head, -); }
void push(LL x, LL k)
{
int pos = x%HASH, i = head[pos];
for (; i != -; i = nxt[i])
if (state[i] == x) { add(f[i], k); return ; }
state[siz] = x, f[siz] = k;
nxt[siz] = head[pos], head[pos] = siz++;
}
}hm[]; void in()
{
scanf("%d %d", &n, &m);
mset(x, -), mset(y, -);
REP(i, , n)
{
scanf("%s", maze[i]+);
REP(j, , m)
{
if (maze[i][j] == 'S') x[] = i, y[] = j;
else if (maze[i][j] == 'X') x[] = i, y[] = j;
else if (maze[i][j] == 'E') x[] = i, y[] = j;
}
}
} bool check(int i, int j)
{
if (maze[i][j] == 'S' && code[m+]) return ;
else if (maze[i][j] == 'X' && code[m+]) return ;
else if (maze[i][j] == 'E' && code[m+]) return ;
else return ;
} void decode(LL x)
{
REP(i, , m+) code[i] = x&, x >>= ;
} LL encode(int i, int j)
{
if (maze[i][j] == 'S') code[m+] = code[j];
else if (maze[i][j] == 'X') code[m+] = code[j];
else if (maze[i][j] == 'E') code[m+] = code[j];
LL ret = ; int cnt = ;
mset(ch, -), ch[] = ;
DWN(t, m+, )
{
if (ch[code[t]] == -) ch[code[t]] = ++cnt;
ret <<= , ret |= ch[code[t]];
}
return ret;
} void dp_blank(int i, int j, int cur)
{
REP(k, , hm[cur].siz-)
{
decode(hm[cur].state[k]);
if (check(i, j)) continue ;
int lef = code[j-], up = code[j], id = ;
if (lef) id = min(id, lef);
if (up) id = min(id, up);
if (lef)
REP(t, , m+) if (code[t] == lef) code[t] = id;
if (up)
REP(t, , m+) if (code[t] == up) code[t] = id;
code[j] = id;
hm[cur^].push(encode(i, j), hm[cur].f[k]);
}
} void dp_block(int i, int j, int cur)
{
REP(k, , hm[cur].siz-)
{
decode(hm[cur].state[k]), code[j] = ;
hm[cur^].push(encode(i, j), hm[cur].f[k]);
}
} void work()
{
int cur = ; LL ans = ;
hm[].clear(), hm[].clear(), hm[].push(, );
REP(i, , n)
REP(j, , m)
{
if (maze[i][j] != '?')
{
if (maze[i][j] == '#') dp_block(i, j, cur);
else dp_blank(i, j, cur);
}
else
{
REP(t, , )
{
if (t < && x[t] != -) continue ;
maze[i][j] = sp[t];
if (maze[i][j] == '#') dp_block(i, j, cur);
else dp_blank(i, j, cur);
}
}
hm[cur].clear(), cur ^= ;
}
REP(i, , hm[cur].siz-)
{
decode(hm[cur].state[i]);
if ((!code[m+]) || (!code[m+]) || (!code[m+])) continue ;
int t = code[m+];
if (code[m+] != t || code[m+] != t) continue ;
add(ans, hm[cur].f[i]);
}
printf("%I64d\n", ans);
} int main()
{
in();
work();
return ;
}
【GDKOI 2016】地图 map 类插头DP的更多相关文章
- GDKOI 2016
GDKOI 2016 day 1 第一题 魔卡少女 题目描述:维护一个序列,能进行以下两个操作:1.将某一个位置的值改变.2.求区间的连续子串的异或值的和. solution 因为序列的数的值都小于\ ...
- 插头dp练习
最近学了插头dp,准备陆续更新插头dp类练习. 学习论文还是cdq那篇<基于连通性状态压缩的动态规划问题>. 基本的想法都讲得很通透了,接下来就靠自己yy了. 还有感谢kuangbin大大 ...
- UVA11270 Tiling Dominoes —— 插头DP
题目链接:https://vjudge.net/problem/UVA-11270 题意: 用2*1的骨牌填满n*m大小的棋盘,问有多少种放置方式. 题解: 骨牌类的插头DP. 1.由于只需要记录轮廓 ...
- HDU 4113 Construct the Great Wall(插头dp)
好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...
- 插头DP专题
建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...
- hdu1693:eat trees(插头dp)
题目大意: 题目背景竟然是dota!屠夫打到大后期就没用了,,只能去吃树! 给一个n*m的地图,有些格子是不可到达的,要把所有可到达的格子的树都吃完,并且要走回路,求方案数 题解: 这题大概是最简单的 ...
- 动态规划之插头DP入门
基于联通性的状态压缩动态规划是一类非常典型的状态压缩动态规划问题,由于其压缩的本质并不像是普通的状态压缩动态规划那样用0或者1来表示未使用.使用两种状态,而是使用数字来表示类似插头的状态,因此.它又被 ...
- hdu1964之插头DP求最优值
Pipes Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...
- ural1519插头DP
1519. Formula 1 Time limit: 1.0 second Memory limit: 64 MB Background Regardless of the fact, that V ...
随机推荐
- nodejs npm install -g 全局安装
1. npm install xxx -g 时, 模块将被下载安装到[全局目录]中. [全局目录]通过 npm config set prefix "目录路径" 来设置. 比如说, ...
- bzoj千题计划295:bzoj3140: [Hnoi2013]消毒
http://www.lydsy.com/JudgeOnline/problem.php?id=3140 如果只有两维,那就是二分图最小点覆盖 现在是三维,但是a*b*c<=5000,说明最小的 ...
- 流媒体技术学习笔记之(十四)FFmpeg进行笔记本摄像头+麦克风实现流媒体直播服务
FFmpeg推送视频流,Nginx RTMP模块转发,VLC播放器播放,实现整个RTMP直播 查看本机电脑的设备 ffmpeg -list_devices true -f dshow -i dummy ...
- 【CodeForces】925 C.Big Secret 异或
[题目]C.Big Secret [题意]给定数组b,求重排列b数组使其前缀异或和数组a单调递增.\(n \leq 10^5,1 \leq b_i \leq 2^{60}\). [算法]异或 为了拆位 ...
- 20155227 2016-2017-2 《Java程序设计》第八周学习总结
20155227 2016-2017-2 <Java程序设计>第八周学习总结 教材学习内容总结 NIO与NIO2 NIO即New IO.java从JDK1.4开始提供了NIO,在JAVA ...
- Hacking Using Beef-Xss
1.环境 hacker:192.168.133.128 os:Kali victims:192.168.133.1 os:win8 2.前期配置 首先进入beef-xss主目录,编辑配置文件,将 ...
- 2017/05/17 java 基础 随笔
- python数据库操作 - MySQL入门【转】
python数据库操作 - MySQL入门 python学院 2017-02-05 16:22 PyMySQL是Python中操作MySQL的模块,和之前使用的MySQLdb模块基本功能一致,PyMy ...
- C# 各版本新特性
C# 2.0 泛型(Generics) 泛型是CLR 2.0中引入的最重要的新特性,使得可以在类.方法中对使用的类型进行参数化. 例如,这里定义了一个泛型类: class MyCollection&l ...
- 测试开发之Django——No4.Django中前端框架的配置与添加
我们在开发一个web项目的时候,虽然我们不是专业开发,但是我们也想要做出来一个美美的前端页面. 这种时候,百度上铺天盖地的前端框架就是我们的最好选择了. 当然,在网上直接下载的框架,我们是不能直接用的 ...