附上学习的博客:https://blog.csdn.net/u013534123/article/details/102762673

大致题意:一个迷宫,里面有很多箱子,你可以向右或者向下走。当你遇到一个或者多个箱子的时候,你可以把箱子往你移动的方向推动,但是不能把箱子推出到墙壁外面。你从左上角出发,问你有多少种方法到右下角。

考虑如果没有箱子,那么就是一个很简单的递推问题,对于一个格子,要么从上面要么从左边来。有箱子的话,由于箱子可以被推动而且不能推到外面,所以我们要考虑是否可以从上面或者下面过来。

还是一样考虑dp,令dp[i][j][0]表示走到位置(i,j)且最后一步是从左边过来的方案,同理dp[i][j][1]表示最后一步从上面来的方案数。然后转移的话,考虑如果是从上面来,我们可以枚举最后一次向右走的位置k,即从(k,j)到(i,j)是一直往下走。如此我们只需要判断是否可以走过来,也即判断(k,j)往下的石头数目是否大于(i,j)下方的格子数,如果大于,那么说明是可以走到(i,j)的,那么把方案数dp[k][j][0]。同理可以得出从左边来,方案数就是dp[i][k][1]。于是有转移方程:

x和y分别表示最前的一个位置,且从这个位置开始到那一行或者那一列的最后的石头数目小于等于后面允许放石头的格子数目。x和y可以用二分比较快速的求,然后显然可以用前缀和来优化,于是复杂度就是O(N^2logN)。然后,仔细想想可以发现x和y是有单调性的,于是可以进一步优化到O(N^2),但是考虑到并没有这个必要而且会复杂一点所以我就没有写了。具体见代码:
——————以上是博客的解法

我另外补充下:

#include<bits/stdc++.h>
#define fi first
#define se second
#define LL long long
#define pb push_back
#define INF 0x3f3f3f3f
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std; const int N = 2010;
const int mod = 1e9 + 7; int dp[N][N][2],sum[N][N][2],R[N][N][2];
char s[N][N]; int main()
{
int n,m;
scc(n,m);
if(n==1&&m==1)
{
puts("1");
return 0;
}
for(int i=0;i<n;i++)
{
scanf("%s",s[i]);
for(int j=0;s[i][j];j++)
if (s[i][j]=='R') R[i][j][0]=R[i][j][1]=1;
}
for(int i=0;i<n;i++)
for(int j=1;j<m;j++)
R[i][j][0]+=R[i][j-1][0];//前缀和表示到列到该点的石头
for(int i=0;i<m;i++)
for(int j=1;j<n;j++)
R[j][i][1]+=R[j-1][i][1];
sum[0][0][0]=sum[0][0][0]=1;
dp[0][0][0]=dp[0][0][1]=1;
for(int i=1;i<n;i++)
{
if (R[n-1][0][1]<=n-i-1) //因为石头只能推到边不能出界,例如该列五个格子有两个格子有石头,那你肯定有效格数到3这一个嘛
dp[i][0][1]+=dp[i-1][0][1];
sum[i][0][0]=dp[i][0][1];//为什么sum的第三维是0呢?请看上图公式
}
for(int i=1;i<m;i++)
{
if (R[0][m-1][0]<=m-i-1)
dp[0][i][0]+=dp[0][i-1][0];
sum[0][i][1]=dp[0][i][0];
}
for(int i=1;i<n;i++)
for(int j=1;j<m;j++)
{
int l=0,r=i-1,mid,t,res=-1;
while(l<=r)//二分找找到第某行,该行小于等于后面允许放石头的格子数目
{
mid=l+r>>1;
t=R[n-1][j][1]-R[mid][j][1];
if (t<=n-i-1) res=mid,r=mid-1;
else l=mid+1;
}
if(res>=0)
{
int tmp=res==0?0:sum[res-1][j][1];
dp[i][j][1]=(sum[i-1][j][1]-tmp+mod)%mod;//前缀和基操,
}
sum[i][jd][0]=(sum[i][j-1][0]+dp[i][j][1])%mod;
l=0,r=j-1,res=-1;
while(l<=r)
{
mid=l+r>>1;
t=R[i][m-1][0]-R[i][mid][0];
if (t<=m-j-1) res=mid,r=mid-1;
else l=mid+1;
}
if (res>=0)
{
int tmp=res==0?0:sum[i][res-1][0];
dp[i][j][0]=(sum[i][j-1][0]-tmp+mod)%mod;
}
sum[i][j][1]=(sum[i-1][j][1]+dp[i][j][0])%mod;
}
printf("%d\n",(dp[n-1][m-1][0]+dp[n-1][m-1][1])%mod);
}

  

cf rock is push 【dp】的更多相关文章

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

    [CodeForces - 1225E]Rock Is Push [dp][前缀和] 标签:题解 codeforces题解 dp 前缀和 题目描述 Time limit 2000 ms Memory ...

  2. Kattis - honey【DP】

    Kattis - honey[DP] 题意 有一只蜜蜂,在它的蜂房当中,蜂房是正六边形的,然后它要出去,但是它只能走N步,第N步的时候要回到起点,给出N, 求方案总数 思路 用DP 因为N == 14 ...

  3. HDOJ 1423 Greatest Common Increasing Subsequence 【DP】【最长公共上升子序列】

    HDOJ 1423 Greatest Common Increasing Subsequence [DP][最长公共上升子序列] Time Limit: 2000/1000 MS (Java/Othe ...

  4. HDOJ 1501 Zipper 【DP】【DFS+剪枝】

    HDOJ 1501 Zipper [DP][DFS+剪枝] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Ja ...

  5. HDOJ 1257 最少拦截系统 【DP】

    HDOJ 1257 最少拦截系统 [DP] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...

  6. HDOJ 1159 Common Subsequence【DP】

    HDOJ 1159 Common Subsequence[DP] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ...

  7. HDOJ_1087_Super Jumping! Jumping! Jumping! 【DP】

    HDOJ_1087_Super Jumping! Jumping! Jumping! [DP] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: ...

  8. POJ_2533 Longest Ordered Subsequence【DP】【最长上升子序列】

    POJ_2533 Longest Ordered Subsequence[DP][最长递增子序列] Longest Ordered Subsequence Time Limit: 2000MS Mem ...

  9. HackerRank - common-child【DP】

    HackerRank - common-child[DP] 题意 给出两串长度相等的字符串,找出他们的最长公共子序列e 思路 字符串版的LCS AC代码 #include <iostream&g ...

随机推荐

  1. NSwag.AspNetCore常用功能介绍

    对于asp.net core 下的Swagger,之前一直用Swashbuckle的,因为官方推荐,再加上有老张的博客助力<从壹开始前后端分离[ .NET Core2.0/3.0 +Vue2.0 ...

  2. iOS多线程知识梳理

    iOS多线程知识梳理 线程进程基础概念 进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 线程 1个进程要想执行任务,必须得有线程(每1个 ...

  3. css字体效果

    text-shadow还没有出现时,大家在网页设计中阴影一般都是用photoshop做成图片,现在有了css3可以直接使用text-shadow属性来指定阴影.这个属性可以有两个作用,产生阴影和模糊主 ...

  4. November 10th, Week 45th, Sunday, 2019

    Perfection has no place in love. 爱从不完美. Perfection has no place in love, and we should always try to ...

  5. 「Shimo使用指南」mac支持pptp协议的小软件

    Mac的好多小伙伴在访问网络设备时觉得远程连接不方便,例如ssh,***登陆都不是很方便,后来又安装了open*** forMac.ISSH等客户端,使用后发现不是很稳定,断线后很久都无法连接等缺点, ...

  6. git结合项目基本使用

    学习博客:1,史上最浅显易懂的Git教程! 2,结合项目具体使用 3,常用命令快速查看 4,git stash 用法总结和注意点 一.git的工作原理和工作流程 Workspace:工作区 Index ...

  7. Node接口实现HTTPS版的

    最近由于自己要做一个微信小程序,接口地址只能是https的,这就很难受了 于是乎,我租了个服务器,搞了个免费的ssl认证 可是呢,我不会搞https接口怎样实现 今天特意花了一天时间来学,来学习 &q ...

  8. hibernate opensission.createSQLquery 问题

    在进行分页查询的时候,通常会用到,页码,每页容量等等的参数进行操作,如下图: query.list()的时候会执行得到所需要的集合的值,在这个过程中, 如果使用自定义的返回参数,比如将日期做一些基本处 ...

  9. 关于java中三种初始化块的执行顺序

    许多小伙伴对于java中的三种初始化块的执行顺序一直感到头疼,接下来我们就来分析一下这三种初始化块到底是怎么运行的.有些公司也会将这个问题作为笔试题目. 下面通过一段代码来看看创建对象时这么初始化块是 ...

  10. 利用百度文字识别API识别图像中的文字

      本文将会介绍如何使用百度AI开放平台中的文字识别服务来识别图片中的文字.百度AI开放平台的访问网址为:http://ai.baidu.com/ ,为了能够使用该平台提供的AI服务,你需要事先注册一 ...