[CodeForces - 1225E]Rock Is Push 【dp】【前缀和】

标签:题解 codeforces题解 dp 前缀和


题目描述

Time limit

2000 ms

Memory limit

524288 kB

Source

Technocup 2020 - Elimination Round 2

Tags

binary search dp *2200

Site

https://codeforces.com/problemset/problem/1225/E

题面

Example

Input1

1 1

.

Output1

1

Input2

2 3

...

..R

Output2

0

Input3

4 4

...R

.RR.

.RR.

R...

Output3

4

题目大意

给定\(n, m\),和一张长宽分别为\(n,m\)的地图。\(\cdot\)代表可以通过,\(R\)代表岩石,无法通过。一个人从左上\((1,1)\)出发,想要到达右下\((n, m)\),他每步只能向下或向右走一格。其间他可以推动与他相邻的一连串岩石一格,根据他从上一步到达这格的方向,但不能将岩石推出地图。问一共有多少条不同的走法?

例如,

\(n = 4, m = 4\),地图为

\[\cdot \cdot \cdot R \\ \cdot R R \cdot \\ \cdot R R \cdot \\ R \cdot \cdot \cdot \\
\]

有如下四条路径,用\(PushD\)代表向下推岩石,用\(PushR\)代表向右推岩石:

  1. \((1,1) \to (2,1) \to(3,1) \to PushR \to(3,2) \to(4,2) \to(4,3) \to(4,4)\)
  2. \((1,1) \to(2,1)\to PushR \to(2,2)\to PushD \to(3,2)\to PushR \to(3,3)\to (4,3)\to (4,4)\)
  3. \((1,1) \to(1,2)\to PushD \to(2,2)\to PushR \to(2,3)\to PushD \to(3,3)\to (3,4)\to (4,4)\)
  4. \((1,1) \to(1,2)\to (1,3)\to PushD \to(2,3)\to (2,4)\to (3,4)\to (4,4)\)

解析

  • 询问从\((1,1)\)走到\((n, m)\)的路径条数,我们也可以反过考虑从\((n, m)\)走到\((1,1)\)的路径条数。

  • 我们令\(dpR[i][j]\)表示从\((i,j)\)的右边一格即从\((i, j + 1)\)到达\((i,j)\)的路径条数,令\(dpD[i][j]\)表示从\((i,j)\)的下边一格即从\((i + 1, j)\)到达\((i,j)\)的路径条数。令\(kD, kR\)分别为从\((i,j)\)到此列最下端和此行最右端的岩石总数。因为岩石可以向右推至地图边缘,所以我们易得$$dpD[i][j] = \sum_{t=i + 1}^{n - kD}dpR[t][j].$$将此列中行坐标在区间\([i+1, n-kD]\)的全部能从右边到达的路径条数都加入\(dpD[i][j]\)中。



    计算\(dpD\)示意图

    同理,我们可得$$dpR[i][j] = \sum_{t=j + 1}^{m - kR}dpD[i][t].$$

  • 为了得到每点的\(kR,kD\),我们需要分别预处理一下每行每列从右至左,从下至上的岩石数量的前缀和。

    \((i,j)\)以右(包括\((i,j)\))的全部岩石数量:\(numR[i][j] = numR[i][j + 1] + (s[i][j] == \,'R')\);

    \((i,j)\)以下(包括\((i,j)\))的全部岩石数量:\(numD[i][j] = numD[i + 1][j] + (s[i][j] == \,'R')\)。



计算岩石总数前缀和

  • 看到如上的累加公式,我们很容易想到要用前缀和来处理。否则时间复杂度会升到立方。

    我们令$$ sumD[i][j] = sumD[i][j + 1] + dpD[i][j], \ sumR[i][j] = sumR[i + 1][j] + dpR[i][j].$$

    则原公式可优化为$$\begin{cases}dpD[n][m] = dpR[n][m] = 1, \dpD[i][j] = \sum_{t=i + 1}^{n - numD[i][j]}dpR[t][j] = sumR[i + 1][j] - sumR[n - numD[i][j] + 1][j], \ dpR[i][j]= \sum_{t=j + 1}^{m - numR[i][j]}dpD[i][t] = sumD[i][j + 1] - sumD[i][m - numR[i][j] + 1] \end{cases}.$$

  • 最后答案即为\(dpD[1][1] + dpR[1][1]\),注意随时取模。

  • 存在两种情况需要特判,详见代码。

以第三个样例为例试举两例,



计算(2,1)的\(dpD\)和\(dpR\)



计算(1,1)的\(dpD\)和\(dpR\)


通过代码

/*
Status
Accepted
Time
108ms
Memory
102804kB
Length
1284
Lang
GNU G++11 5.1.0
Submitted
2019-12-23 18:13:00
RemoteRunId
67463663
*/ #include <bits/stdc++.h>
using namespace std; const int MOD = 1e9 + 7; //随时取模.
const int MAXN = 2e3 + 50; char s[MAXN][MAXN];
int numD[MAXN][MAXN], numR[MAXN][MAXN], sumD[MAXN][MAXN], sumR[MAXN][MAXN], dpD[MAXN][MAXN], dpR[MAXN][MAXN];
int n, m; int main()
{
scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++)
scanf("%s", s[i] + 1); if(s[1][1] == 'R' || s[n][m] == 'R'){ //第一种特判情况,起点或终点被岩石占上,则没有路径可以到达.
printf("0");
return 0;
} if(n == 1 && m == 1){ //第二种特判情况,地图大小为1*1,则直接输出1.
printf("1");
return 0;
} for(int i = n; i >= 1; i --){ //从右下开始预处理岩石总数前缀和.
for(int j = m; j >= 1; j --){
numD[i][j] = numD[i + 1][j] + (s[i][j] == 'R');
numR[i][j] = numR[i][j + 1] + (s[i][j] == 'R');
}
} sumD[n][m] = sumR[n][m] = dpD[n][m] = dpR[n][m] = 1;
for(int i = n; i >= 1; i --){ //从右下开始状态转移.
for(int j = m; j >= 1; j --){
if(i == n && j == m) continue;
dpD[i][j] = (sumR[i + 1][j] - sumR[n - numD[i + 1][j] + 1][j]) % MOD;
dpR[i][j] = (sumD[i][j + 1] - sumD[i][m - numR[i][j + 1] + 1]) % MOD; sumD[i][j] = (sumD[i][j + 1] + dpD[i][j]) % MOD;
sumR[i][j] = (sumR[i + 1][j] + dpR[i][j]) % MOD;
}
} printf("%d", (dpR[1][1] + dpD[1][1] + 2ll * MOD) % MOD); //得出答案.
return 0;
}

[CodeForces - 1225E]Rock Is Push 【dp】【前缀和】的更多相关文章

  1. Codeforces Round #596 (Div. 2, based on Technocup 2020 Elimination Round 2) E. Rock Is Push dp

    E. Rock Is Push You are at the top left cell (1,1) of an n×m labyrinth. Your goal is to get to the b ...

  2. Codeforces 332B Maximum Absurdity(DP+前缀和处理)

    题目链接:http://codeforces.com/problemset/problem/332/B 题目大意:给你n个数和一个整数k,要求找到不相交的两个长度为k的区间,使得区间和最大,输出这两个 ...

  3. Codeforces 1247E. Rock Is Push

    传送门 显然考虑 $dp$ ,设 $fx[i][j]$ 表示从 $(i,j)$ 出发往下走一格,最终到达 $(n,m)$ 的方案数,$fy[i][j]$ 表示从 $(i,j)$ 出发往右走一格,最终到 ...

  4. CodeForces 816B Karen and Coffee(前缀和,大量查询)

    CodeForces 816B Karen and Coffee(前缀和,大量查询) Description Karen, a coffee aficionado, wants to know the ...

  5. HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化

    HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化 n个节点n-1条线性边,炸掉M条边也就是分为m+1个区间 问你各个区间的总策略值最少的炸法 就题目本身而言,中规中矩的 ...

  6. [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)

    [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...

  7. [Codeforces712D] Memory and Scores(DP+前缀和优化)(不用单调队列)

    [Codeforces712D] Memory and Scores(DP+前缀和优化)(不用单调队列) 题面 两个人玩游戏,共进行t轮,每人每轮从[-k,k]中选出一个数字,将其加到自己的总分中.已 ...

  8. T2988 删除数字【状压Dp+前缀和优化】

    Online Judge:从Topcoder搬过来,具体哪一题不清楚 Label:状压Dp+前缀和优化 题目描述 给定两个数A和N,形成一个长度为N+1的序列,(A,A+1,A+2,...,A+N-1 ...

  9. [CF467C] George and Job - DP,前缀和

    简单dp + 前缀和 你谷这乱标难度的风气真是-- #include <bits/stdc++.h> using namespace std; #define int long long ...

随机推荐

  1. php array_combine()函数 语法

    php array_combine()函数 语法 作用:通过合并两个数组来创建一个新数组,其中的一个数组是键名,另一个数组的值为键值.dd马达价格 语法:array_combine(keys,valu ...

  2. 【2019 Multi-University Training Contest 8】

    01: 02: 03:https://www.cnblogs.com/myx12345/p/11655876.html 04: 05: 06:https://www.cnblogs.com/myx12 ...

  3. UE4 中的Blutilities

    该功能是为编辑器中的简单扩展功能而设置的. 一般而言用蓝图在编辑器中做功能扩展都会用到Construction Script,但该功能有一些缺陷: 首先在actor发生任何变化(包括Transform ...

  4. 如何利用阿里视频云开源组件,快速自定义你的H5播放器?

    摘要: Aliplayer希望提供一种方便.简单.灵活的机制,让客户能够扩展播放器的功能,并且Aliplayer提供一些组件的基本实现,用户可以基于这些开源的组件实现个性化功能,比如自定义UI和自己A ...

  5. linux的shell脚本运行python程序

    可以说和windows里的bat是一样的. python3 /opt/pyweibo/get_user_info.py 104501 104502 104503

  6. MySql使用mysqldump 导入与导出方法总结

    导出数据库数据:首先打开cmd进入MySQL的bin文件夹下 1.导出education数据库里面的users表的表数据和表结构(下面以users表为例) mysqldump -u[用户名] -h[i ...

  7. day22—一个AngularJS框架应用toDoList

    转行学开发,代码100天——2018-04-07 今天用AngularJS照着课程写了一个案例,即toDoList,记事清单效果. 主要实现以下效果: 1.通过文本框添加内容,同时添加事件列表.主要用 ...

  8. Jenkins持续集成_01_Mac安装配置

    前言 Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建.测试和部署软件.在自动化测试中,用来持续集成,跑定时任务进行定时自动化监测.更详细介绍可查看jenkins官网: ...

  9. 阅读笔记05-架构师必备最全SQL优化方案(1)

    一.优化的哲学 1.优化可能带来的问题? 优化不总是对一个单纯的环境进行,还很可能是一个复杂的已投产的系统: 优化手段本来就有很大的风险,只不过你没能力意识到和预见到: 任何的技术可以解决一个问题,但 ...

  10. python网络编程之粘包

    一.什么是粘包 须知:只有TCP有粘包现象,UDP永远不会粘包 粘包不一定会发生 如果发生了:1.可能是在客户端已经粘了 2.客户端没有粘,可能是在服务端粘了 首先需要掌握一个socket收发消息的原 ...