#luogu整理 P1244 青蛙过河

luogu P1244 青蛙过河

这个题太骚了。。。。

题目描述

有一条河,左边一个石墩((A) 区)上有编号为 (1,2,ldots ,n)(n) 只青蛙,河中有 (k) 个荷叶(C 区),还有 (h) 个石墩(D 区),右边有一个石墩(B 区),如下图所示。(n) 只青蛙要过河(从左岸石墩 A 到右岸石墩 B),规则为:

  • 石墩上可以承受任意多只青蛙,荷叶只能承受一只青蛙(不论大小);

  • 青蛙可以:(A→B(表示可以从 A 跳到 B,下同),A o C,A o D,C o B,D o B,D o C,C o D)

  • 当一个石墩上有多只青蛙时,则上面的青蛙只能跳到比它大一号的青蛙上面。

你的任务是对于给出的 (h,k),计算并输出最多能有多少只青蛙可以根据以上规则顺利过河。

输入格式

输入两个整数 (h,k)

输出格式

一个整数,表示最多能有多少只青蛙可以根据以上规则顺利过河。

输入样例

2 3

输出样例

16

数据范围

(h≤20,k leq 10^3)

思路

先理解一下题意:青蛙一开始都在左边岸上,且先跳出的青蛙体型比后跳出的青蛙体型小(也就是先跳出的青蛙能坐在后跳出的青蛙上),青蛙可以选择直接向河对岸跳,也可以从荷叶区、河墩区中转一下到对岸。需要注意的是:一片河墩上面的第一个青蛙,决定了这个河墩上青蛙的最大体型。(有点类似汉诺塔)

动态规划,设(f[h][k])表示用了h个河墩,k个荷叶最多的过河数量,那么我们可以知道(f[0][k] = k+1)(前k个先到荷叶上,最后一个直接到河对岸,前k个再到对岸)。

如果多用一个河墩,我们就有:(f[1][k] = f[0][k] + f[0][k] = 2f[0][k])含义:先让第一队青蛙用这k个荷叶中转到河墩区河墩上(也就是(f[0][k])只),再用让第二队青蛙通过荷叶直接到对岸((f[0][k])只)。最后让第一队的青蛙继续利用荷叶中转到对岸。整个过程符合题目要求。

两个河墩,我们就可以让第一队青蛙利用k个荷叶和一号河墩中转((f[1][k])只),到河墩区的二号河墩上,再让二队青蛙利用k个荷叶中转到一号河墩上((f[0][k])只),再让第三队的青蛙直接利用荷叶中转到对岸((f[0][k])只),最后二队青蛙过岸、一队青蛙过岸,就算是完成了,总数是(f[2][k] = f[0][k]+f[0][k]+f[1][k] = 4f[0][k])只。

最终通过整理,我们发现:(f[h][k] = f[0][k] imes 2^h = (k+1) imes 2^h)

代码

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int main(){
    int h,k;
    cin >> h >> k;
    cout << (k+1)*(1 << h) << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/Cao-Yucong/p/12882217.html