【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 ...
随机推荐
- haproxy acl访问限制IP
http-request: 7层过滤 tcp-request content: tcp层过滤,四层过滤 注意 四层 采用 accept和reject 七层采用 allow和deny ...
- Why is my Spring @Autowired field null?
spring有@Autowired 空指针异常 https://stackoverflow.com/questions/19896870/why-is-my-spring-autowired-fiel ...
- Eclipse的个性化设置
Eclipse的个性化设置 1. 在Eclipse中查看JDK源码的配置 a. 点 “window”-> "Preferences" -> "Java&quo ...
- 小记 HTML5 file对象
<input type="file" id="myfile" multiple> 这是个很普通的 file 上传组件,multiple 是支持多选, ...
- [转载]Remote Desktop Manager 9.0.10.0 Enterprise 附企业版注册码 (强大的远程控制软件)
http://www.52xiazai.net/pcsoft/network/yuanchen/20131206/2429.html
- 20155206 2016-2017-2 《Java程序设计》第6周学习总结
20155206 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 串流设计 流(Stream)是对「输入输出」的抽象,注意「输入输出」是相对程序而言的. Ja ...
- 第5月第21天 bugly ios证书位置
1.bugly 一. 本地测试 补丁编写规则参见: JSPatch 将补丁文件main.js拖拽到工程内: 开启 BuglyConfig 中的热更新本地调试模式: BuglyConfig *confi ...
- CentOS配置源
一.源列表 aliyun源 #各系统版本repo文件对应的下载操作 CentOS wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.al ...
- linux系统基本排查
1.查看内存使用情况 free -g 当观察到free栏已为0的时候,表示内存基本被吃完了,那就释放内存吧. 释放内存: sync echo 3 > /proc/sys/vm/drop_cach ...
- 6 个 Linux 运维典型问题,大牛的分析解决思路在这里 【转】
作为一名合格的 Linux 运维工程师,一定要有一套清晰.明确的解决故障思路,当问题出现时,才能迅速定位.解决问题,这里给出一个处理问题的一般思路: 重视报错提示信息:每个错误的出现,都是给出错误提示 ...