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;
}