P1244 青蛙过河

Posted xcg123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1244 青蛙过河相关的知识,希望对你有一定的参考价值。

原题链接  https://www.luogu.com.cn/problem/P1244

技术图片

 

 

技术图片

 

 

闲话时刻

CSP-S 考炸了,心情低落,开始水起了橙题  我觉得 dp 这一类的题在 CSP-S 中考的挺常见的(当然还有树论),作为一个 dp 菜鸡准备开始重新学 dp,暂且由这个题来作为新起点吧qwq 。

题目大意

河的两岸各有一只石墩 A , B,河中有 h 个石墩和 k 个荷叶,问最多能有多少只青蛙能够顺利过河,过河规则如下:

1. 每个石墩可以像叠罗汉一样载若干只青蛙,但是每只青蛙只能踩在比它编号大 1 的青蛙的头上;每个荷叶只能载一只青蛙;

2.  只有当一只青蛙的头上没有青蛙时,才能移动这只青蛙;

3. 一开始在石墩 A 上的时候,青蛙们排列符合在石墩上的规则,且都跳到石墩后也要满足该规则;

4. 青蛙可以直接从石墩 A 跳到石墩 B;

5. 只要从石墩 A 跳出去后,就不能再回到石墩 A 了;一旦跳到石墩 B,就不能再跳回去了; 

6. 本题的青蛙不会游泳;

题解

这道挺有意思的,同时还颇具思维难度,我们可以从简单到复杂依次去考虑;

我们设一个答案数组:ans [ i ][ j ] 表示 h=i,k=j 时的答案;

① 先看 h=0 的情况:

也就是河中只有荷叶,没有石墩的情况,看一个简单的例子:

技术图片

 

 

技术图片

 

技术图片

 

技术图片

 

技术图片

 

技术图片

 

技术图片

 

技术图片

 

技术图片

ans [ 0 ][ 3 ] = 4; 

我们可以发现:

当 h=0 的时候,每个荷叶可以作为一只青蛙的落脚点,然后一开始的石墩 A 也可以作为一只青蛙的落脚点(且只能是编号最大的那只青蛙的落脚点),这样得话一共能有 k+1 只青蛙顺利过河 。

ans [ 0 ][ k ] = k+1; 

 

② 看 h≠0 的情况:

还是上面的那个例子,只不过河里多了一个石墩,那么怎么办呢?

技术图片

 

其实,河中的石墩和河岸的石墩 B 都是能够载若干只青蛙的,且它们两个的排列规则是相同的,我们不妨暂且将河中的这一个石墩钦定为石墩 B,然后像刚刚那样的跳法将这四只青蛙都跳到河中石墩来

技术图片

 

技术图片

 

技术图片

 

技术图片

 

这一波操作之后,发现河中的这个石墩的最上面那只青蛙是 1,已经不能再往上跳青蛙了,我们可以暂且忽略这个石墩的存在了,那么河中只剩下了三个荷叶,也就是 h=0,k=3 的情况! 

统计答案:

我们是先将河中石墩暂且看做是 h=0,k=3 情况下的石墩 B,那么这个石墩上最多载的青蛙就是 ans [ 0 ][ 3 ],然后剩下的就是 h=0,k=3 的情况了,那么又是一个 ans [ 0 ][ 3 ],最后的答案 ans [ 1 ][ 3 ] = ans [ 0 ][ 3 ] + ans [ 0 ][ 3 ] = 2 * ans [ 0 ][ 3 ];

 

按着这个思路,我们想一下 ans [ 2 ][ 3 ] 是多少:

也就是 h=1,k=3 的情况下又多了个石墩,那么我们把这个多的石墩看做是 h=1,k=3 情况下的石墩 B,那这个石墩上可以载的青蛙数就是 ans [ 1 ][ 3 ],这个石墩载满后,剩下的就是 h=1,k=3 的情况了,答案再加个 ans [ 1 ][ 3 ],最后的答案 ans [ 2 ][ 3 ] = ans [ 1 ][ 3 ] + ans [ 1 ][ 3 ] = 2 * ans [ 1 ][ 3 ];

由此我们可以发现:对于任何一个 h,k 的情况,我们都暂且可以把多出来的那个石墩看做是石墩 B,那么这个石墩上载的青蛙数最多为 ans [ h-1 ][ k ],这个石墩载满后,剩下的情况又是一个 ans [ h-1 ][ k ],则 ans [ h ][ k ] = ans [ h-1 ][ k ] + ans [ h-1 ][ k ] = 2 * ans [ h-1 ][ k ],这是个递归的过程;

因为河中多一个石墩答案就 ×2,所以也不难从中发现通项式:

ans [ h ][ k ] = 2h * k (相比于 h=0 的情况多了 h 个石墩,所以答案要乘 h 个 2,也就是 2h

那么我们就可以愉快的 O ( 1 ) 出答案啦,超短代码如下:

#include<iostream>
using namespace std;
int h,k;
int main()
{
    cin>>h>>k;
    cout<<(1<<h)*(k+1);   //注意h=0的情况下答案是k+1 
}

Emmm,又是一道挂着 dp 标签的找规律题qwq 

   

以上是关于P1244 青蛙过河的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P1244 青蛙过河

P1244 青蛙过河

洛谷P1244 青蛙过河 DP/思路

403 Frog Jump 青蛙过河

青蛙过河(二分+并查集)

递归与递推青蛙过河