cf rock is push 【dp】
附上学习的博客: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】的更多相关文章
- [CodeForces - 1225E]Rock Is Push 【dp】【前缀和】
[CodeForces - 1225E]Rock Is Push [dp][前缀和] 标签:题解 codeforces题解 dp 前缀和 题目描述 Time limit 2000 ms Memory ...
- Kattis - honey【DP】
Kattis - honey[DP] 题意 有一只蜜蜂,在它的蜂房当中,蜂房是正六边形的,然后它要出去,但是它只能走N步,第N步的时候要回到起点,给出N, 求方案总数 思路 用DP 因为N == 14 ...
- HDOJ 1423 Greatest Common Increasing Subsequence 【DP】【最长公共上升子序列】
HDOJ 1423 Greatest Common Increasing Subsequence [DP][最长公共上升子序列] Time Limit: 2000/1000 MS (Java/Othe ...
- HDOJ 1501 Zipper 【DP】【DFS+剪枝】
HDOJ 1501 Zipper [DP][DFS+剪枝] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Ja ...
- HDOJ 1257 最少拦截系统 【DP】
HDOJ 1257 最少拦截系统 [DP] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- HDOJ 1159 Common Subsequence【DP】
HDOJ 1159 Common Subsequence[DP] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ...
- HDOJ_1087_Super Jumping! Jumping! Jumping! 【DP】
HDOJ_1087_Super Jumping! Jumping! Jumping! [DP] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: ...
- POJ_2533 Longest Ordered Subsequence【DP】【最长上升子序列】
POJ_2533 Longest Ordered Subsequence[DP][最长递增子序列] Longest Ordered Subsequence Time Limit: 2000MS Mem ...
- HackerRank - common-child【DP】
HackerRank - common-child[DP] 题意 给出两串长度相等的字符串,找出他们的最长公共子序列e 思路 字符串版的LCS AC代码 #include <iostream&g ...
随机推荐
- 【Cef编译】 CefSharp编译失败,检测到“RuntimeLibrary”的不匹配项: 值“MT_StaticRelease”不匹配值“MD_DynamicRelease”
编译CefSharp生成后一个libcef_dll_wrapper.lib时,供CefSharp使用.结果CefSharp编译的时候报错.遇到以下异常: libcef_dll_wrapper.lib( ...
- Bootstrap4 本地编译运行
Step1. 获取Bootstrap源代码 https://github.com/twbs/bootstrap Step2. 进入目录并切换npm源 npm --registry https://re ...
- Viewpager+Fragment 跳转Activity报错android.os.TransactionTooLargeException: data parcel size xxxxx bytes
Viewpager + Fragment 跳转Activity报错android.os.TransactionTooLargeException: data parcel size xxxxx byt ...
- Android8.1 SystemUI源码分析之 Notification流程
代码流程 1.先看UI显示,StatuBar加载 CollapsedStatusBarFragment 替换 status_bar_container(状态栏通知显示区域) SystemUI\src\ ...
- Android WebView与H5联调技巧
版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/78 背景: 突然想写一篇关于Android WebView ...
- json属性里面出现特殊字符怎么获取属性
直接上代码. 这样的 获取这个object后需要获取里面的书属性,但是正常情况下是XX.属性名.但是属性名有特殊符号.这时候我们可以这样. XX['属性名']['属性名']....可以一直这样写 XX ...
- Linux基础命令---ntpstat显示时间服务器同步
ntpstat ntpstat指令用于显示本机上一次和服务器同步时间的情况. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora. 1.语法 ntpstat 2 ...
- JavaScript-----13.内置对象 Math()和Date()
1. 内置对象 js对象分为3种:自定义对象(var obj={}).内置对象.浏览器对象. 前两种对象是js基础内容,属于ECMAScript,第三个浏览器对象是js独有的.讲js API的时候会讲 ...
- TKinter当Label绑定bind事件时传参方法
记录下tkinter的 当在label绑定bind事件时,遇到需要传参时的解决方法(因为有event存在 所以不能直接传参) https://www.cnblogs.com/liyuanhong/ar ...
- 基于 CAS 无锁实现的 Disruptor.NET 居然慢于 BlockingCollection,是真的吗?
StackOverflow 有人说自己的Disruptor.NET 代码比 BlockingCollection 还有慢 2 倍,并且把完整代码贴出,楼下几个老外也的回复说了一堆,但是没研究出个所以然 ...