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 ...
随机推荐
- bzoj 2144: 跳跳棋——倍增/二分
Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...
- 【51NOD-5】1293 球与切换器
[算法]DP [题解]f[i][j][0]表示在i,j位置往下走的球数,f[i][j][1]表示在i,j位置往右走的球数,经过i,j的球若为-1则(num+1)/2往下,其余往右.+1类似. 转移见代 ...
- 【洛谷 P3628】 [APIO2010]特别行动队 (斜率优化)
题目链接 斜率优化总结待补,请催更.不催更不补 \[f[i]=f[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c\] \[=f[j]+a*sum[i]^2+a*s ...
- canvas_简单练习
效果图 实现原理: 1.定义canvas标签. 2.获取canvas标签节点,创建canvas2D. 3.在canvas进行画图. 效果代码: <!DOCTYPE html> <ht ...
- spring boot web 入门
① 新建一个maven项目. ② pom中parent设为 spring-boot-starter-parent .建议使用最新的 RELEASE 版本.否则可能需要设置 <repositori ...
- php中的base64写shell
<?php system(base64_decode($_GET['info'])); #http://localhost/1.php?info=d2hvYW1p #这只是一个例子 ?>
- Python爬虫音频数据
一:前言 本次爬取的是喜马拉雅的热门栏目下全部电台的每个频道的信息和频道中的每个音频数据的各种信息,然后把爬取的数据保存到mongodb以备后续使用.这次数据量在70万左右.音频数据包括音频下载地址, ...
- vue做购物车
写一点废话,昨天敲代码找bug,找了好久都没找到,后来一哥们找到他说,找代码的bug就像男女朋友吵架,女问男你错了没,男说错啦,女再问错哪了,男傻眼了不知道错哪.在找代码的过程中一直知道我错啦就是找不 ...
- [New learn] 网络基础-网络操作
代码:https://github.com/xufeng79x/NETOperation 1.简介 主要记录基本的网络操作步骤,get/post关系和区别和文件上传实现. 2.准备 需要服务器端,如果 ...
- hit-testing机制介绍
1.简介 寻找处理触摸事件的view的过程为hit-testing,找到的能够处理触摸事件的view叫做hit-test view. 2.机制介绍 假设下图为我们的手机屏幕,当我们假设点击了view ...