Topcoder Srm 671 Div2 1000 BearDestroysDiv2
## $>Topcoder \space Srm \space 671 \space Div2 \space 1000 \space BearDestroysDiv2
题目大意 : 有一个 \(W \times H\) 的网格,每一格上有一棵树和一个随机字母 \(S\) 或 \(E\) ,有一只熊在左上角,按从上到下从左到右的顺序遍历每一行每一列,如果其遇到一棵可以推倒的树,就尽可能按照字母表示的方向 (向下,向右) 推倒它,然后其推倒方向的下一棵树就不能被推倒了,同时树不能被推倒在边界之外,求对于所有可能的网格图,树的被推倒个数总和对 \(Mod\) 取模的值 。
\(1 \leq W \leq 7 \ ,1 \leq H \leq 40\)
解题思路 :
观察到 \(W\) 比较小,不妨对列进行状态压缩,又因为直接状压每一列后效性很难讨论,所以维护轮廓线来 \(dp\) 转移.
设 \(f[i][r][j][s]\) 表示第 \(i\) 行维护的轮廓线断点在 \(r\), 轮廓线上的点的状态为 \(s\) ,到目前位置推倒了 \(j\) 棵树的答案
考虑直接将轮廓线上的点定义为 {没推倒,向\(E\)推倒,向\(S\)推倒} 三种不仅无法很好描述状态来转移,复杂度也差强人意
观察发现,对于轮廓线上的点转移到下一状态时,被推倒和因为其他树推倒在它身上导致不能推倒是等价的.
换一种说法,轮廓线上的点对后面状态的更新当且仅当取决于其在此刻能否被推倒,不妨用 \(0\) 表示可以被推倒 \(1\)表示不行
如图所示,绿色的是当前的轮廓线,红色的是要被更新的轮廓线,当前要把点 \(P_2\) 加到轮廓线中.
如果 \(mask(P_0) = 0\) 说明 \(P_0\) 能推倒但因为一些原因没有推倒其右边的点,根据题意,此时 \(P_0\) 必须要向下推倒
考虑 \(P_0\) 被向下推倒了之后,\(P_1\) 就不能向右推倒了,所以 \(P_1\) 如果要向下推倒选 \(S, E\) 都可以.
\(P_2\) 因为被卡住了不能动,所以选 \(S, E\) 也都可以,所以转移的时候方案数的系数为 \(2 \times \max(2 \times [mask(P_1) = 0], 1)\)
如果 \(mask(P_0) = 1\) 且 \(maxk(P_1) = 0\)
此时 \(P_1\) 既可以向下推倒又可以向右推倒,向下的情况只需要保留当且轮廓线的状态即可
考虑 \(P_1\) 要向右推倒,当且仅当 \(P_0\) 没有向下推倒且 \(P_1\) 上的字母为 \(E\) , 所以转移的时候方案数的系数为 \(2\)
如果都不能推倒,那么只需要保留当前轮廓线状态并添加新的点 \(P_2\) 即可
考虑边界的情况,对于所有右边界和下边界,推倒的树的字母都可以选择两种
特别的,对于下边界上的点,\(P_1\) 只能选择向右推倒,对于最后状态产生的未推倒的树,都可以选取两种颜色
所以只需要枚举轮廓线和推倒的树的个数,分类讨论转移
此题细节比较多,建议多算几遍系数,复杂度是 \(O(\frac{W^2H}{2}\times2^W)\)
/*program by mangoyang*/
typedef long long ll;
ll f[45][10][176][1<<7], Mod;
inline void update(ll &x, ll y){ (x += y) %= Mod; }
int BearDestroysDiv2::sumUp(int W, int H, int MOD){
memset(f, 0, sizeof(f));
int all = W * H / 2 + 1, lim = (1 << W) - 1;
f[0][W][0][lim] = 1, Mod = MOD;
for(int i = 1; i <= H; i++){
for(int j = 0; j <= all; j++)
for(int s = 0; s <= lim; s++) f[i][0][j][s] = f[i-1][W][j][s];
for(int r = 0; r < W; r++)
for(int j = 0; j <= all; j++)
for(int s = 0; s <= lim; s++){
if(!((1 << r) & s)){
ll s2 = (r == W - 1) ? 2 : 1, s1 = 1;
if(r && !((1 << r - 1) & s) && i != H) s1 = 2;
update(f[i][r+1][j+1][s|(1<<r)], f[i][r][j][s] * 2 * s2 * s1);
}
else{
if(i < H) update(f[i][r+1][j][s^(1<<r)], f[i][r][j][s]);
if(r && !((1 << r - 1) & s)){
ll s2 = (i == H) ? 2 : 1;
update(f[i][r+1][j+1][s|(1<<r)|(1<<r-1)], f[i][r][j][s] * 2 * s2);
}
else if(i == H) update(f[i][r+1][j][s^(1<<r)], f[i][r][j][s]);
}
}
}
ll ans = 0;
for(int j = 1; j <= all; j++)
for(int s = 0; s <= lim; s++) if(f[H][W][j][s]){
ll res = 1;
for(int i = 0; i < W; i++)
if(!((1 << i) & s)) res *= 2;
update(ans, f[H][W][j][s] * j * res);
}
return ans;
}
Topcoder Srm 671 Div2 1000 BearDestroysDiv2的更多相关文章
- Topcoder Srm 673 Div2 1000 BearPermutations2
\(>Topcoder \space Srm \space 673 \space Div2 \space 1000 \space BearPermutations2<\) 题目大意 : 对 ...
- TopCoder SRM 660 Div2 Problem 1000 Powerit (积性函数)
令$f(x) = x^{2^{k}-1}$,我们可以在$O(k)$的时间内求出$f(x)$. 如果对$1$到$n$都跑一遍这个求解过程,时间复杂度$O(kn)$,在规定时间内无法通过. 所以需要优化. ...
- TopCoder SRM 301 Div2 Problem 1000 CorrectingParenthesization(区间DP)
题意 给定一个长度为偶数的字符串.这个字符串由三种括号组成. 现在要把这个字符串修改为一个符合括号完全匹配的字符串,改变一个括号的代价为$1$,求最小总代价. 区间DP.令$dp[i][j]$为把子 ...
- SRM 146 DIV2 1000
Problem Statement A well-known riddle goes like this: Four people are crossing an old bridge. T ...
- 求拓扑排序的数量,例题 topcoder srm 654 div2 500
周赛时遇到的一道比较有意思的题目: Problem Statement There are N rooms in Maki's new house. The rooms are number ...
- Topcoder srm 632 div2
脑洞太大,简单东西就是想复杂,活该一直DIV2; A:水,基本判断A[I]<=A[I-1],ANS++; B:不知道别人怎么做的,我的是100*N*N;没办法想的太多了,忘记是连续的数列 我们枚 ...
- topcoder SRM 628 DIV2 BracketExpressions
先用dfs搜索所有的情况,然后判断每种情况是不是括号匹配 #include <vector> #include <string> #include <list> # ...
- topcoder SRM 628 DIV2 BishopMove
题目比较简单. 注意看测试用例2,给的提示 Please note that this is the largest possible return value: whenever there is ...
- Topcoder SRM 683 Div2 B
贪心的题,从左向右推过去即可 #include <vector> #include <list> #include <map> #include <set&g ...
随机推荐
- 关于RecylerView:1.在ScrollView的RecylerView滑动事件的处理。2.item之间的距离 小数取整
1.在ScrollView的RecylerView滑动事件的处理. 在布局文件中在RecylerView外包裹一层相对布局 2.RecylerView item之间的距离 (1)编写SpaceItem ...
- Kaggle 数据挖掘比赛经验分享(转)
原作者:陈成龙 简介 Kaggle 于 2010 年创立,专注数据科学,机器学习竞赛的举办,是全球最大的数据科学社区和数据竞赛平台.笔者从 2013 年开始,陆续参加了多场 Kaggle上面举办的比 ...
- arduino 用电位器调节LED闪烁频率
int dianwei; int led = 13; void setup() { // put your setup code here, to run once: Serial.begin(9 ...
- JSOI2018简要题解
来自FallDream的博客,未经允许,请勿转载,谢谢. 有幸拜读到贵省的题目,题的质量还不错,而且相比zjoi可做多了,简单发一下题解吧. 还有就是,怎么markdown在博客园上的代码这么丑啊 「 ...
- Java中基于HotSpot虚拟机的垃圾收集器
名称 过程 优缺点 Serial 进行垃圾收集时,必须暂停其他所有的工作进程,直到它收集结束.是一个单线程收集器. Stop the world. 新生代收集器. 手工设置新生代的大小:-Xmn Ed ...
- python基础=== itertools介绍(转载)
原文链接:http://python.jobbole.com/85321/ Python提供了一个非常棒的模块用于创建自定义的迭代器,这个模块就是 itertools.itertools 提供的工具相 ...
- HDU 6146 Pokémon GO DP,计数
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6146 题意:~ 解法:原题..http://blog.csdn.net/y990041769/arti ...
- 关闭自动弹出照片自动弹出iTunes以及关闭手机照片流
关闭自动弹出照片自动弹出iTunes以及关闭手机照片流 如何阻止iPhone连接Mac后自动弹出照片? 时间:2015/6/18 17:07:15来源:本站原创作者:Chenjh我要评论 很多新 iP ...
- vim常用命令(复习版)(转)
原文链接:http://blog.csdn.net/love__coder/article/details/6739670 1.光标移动 上:k 下:j 左:l 『字母L小写』 右:h 上一行行首:- ...
- Window Server 2008 R2 安装 Share Point 2013
原文地址:http://www.cnblogs.com/jianyus/p/3631905.html