NOI2000 青蛙过河[递推]

也许更好的阅读体验

\(\mathcal{Description}\)

原题链接:
Comet OJ
洛谷

大小各不相同的一队青蛙站在河左岸的石墩(记为A)上,要过到对岸的石墩(记为D)上去。河心有几片菏叶(分别记为\(Y1​…Ym​)\)和几个石墩(分别记为\(S1…Sn)\)。图示如下:

49776cae2.md.png

青蛙的站队和移动方法规则如下:

每只青蛙只能站在荷叶、石墩,或者仅比它大一号的青蛙背上(统称为合法的落脚点);
一只青蛙只有背上没有其它青蛙的时候才能够从一个落脚点跳到另一个落脚点;
青蛙允许从左岸A直接跳到河心的石墩、荷叶和右岸的石墩D上,允许从河心的石墩和荷叶跳到右岸的石墩D上;
青蛙在河心的石墩之间、荷叶之间以及石墩和荷叶之间可以来回跳动;
青蛙在离开左岸石墩后,不能再返回左岸;到达右岸后,不能再跳回;
假定石墩承重能力很大,允许无论多少只青蛙都可呆在上面。但是,由于石墩的面积不大,至多只能有一只青蛙直接站在上面,而其他的青蛙只能依规则1落在比它大一号的青蛙的背上。
荷叶不仅面积不大,而且负重能力也有限,至多只能有一只青蛙站在上面。
每一步只能移动一只青蛙,并且移动后需要满足站队规则;
在一开始的时候,青蛙均站在A上,最大的一只青蛙直接站在石墩上,而其它的青蛙依规则6站在比其大一号的青蛙的背上。

青蛙希望最终能够全部移动到D上,并完成站队。

设河心有\(m\)片荷叶和\(n\)个石墩,请求出这队青蛙至多有多少只,在满足站队和移动规则的前提下,能从A过到D。

例如,在m=1且 n=1时,河心有一片荷叶\((Y1​)\)和一个石墩\((S1​)\),此时至多有\(4\)只青蛙能够过河(由小到大称为\(1、2、3、4)\),过河的一种方法为:

12449fec1.md.png

此例中,当河心有一片荷叶和一个石墩时,4只青蛙能够跳动9步过河。

输入描述

仅有两行,每一行仅包含一个整数和一个换行/回车符。第一行的数字为河心的石墩数\(n(0≤n≤25)\),第二行为荷叶数\(m(0≤m≤25)\)

输出描述

仅包含一个数字和一个换行/回车符。该数字为在河心有\(n\)个石墩和\(m\)片荷叶时,最多能够过河的青蛙的只数。

\(\mathcal{Solution}\)

简单来说就是在石墩上青蛙可以类似\(Hanoi\)问题\((汉诺塔)\)地叠着
我们想叠得越多越好,显然我们既然有办法把它叠起来,用叠的逆过程就可以把它们全部合法的放到河对岸
所以我们只要考虑如何叠
设有\(n\)片荷叶,\(k\)个石墩
\(k=0\),那么我们在每片荷叶上放一只青蛙,然后从岸上直接跳到对面一只青蛙,可以有\(n+1\)只青蛙过岸
\(k=1\),那么我们可以在这个石墩上叠\(n+1\)只青蛙,然后就又变为\(k=0\)的情况
类似地,每多一个石墩就可以利用原来的\(k-1\)个石墩把它们的青蛙全部放到这上面来,这样就增加了一倍的青蛙可以过岸

换个想法,我们可以将每个石墩当成对岸的石墩,然后我们就先直接跳一个青蛙上来,再把当前的青蛙\(f_{k-1}-1\)全部转移到这个石墩上面,然后原来的石墩就都空了,于是可以再把原来石墩上再放\(f_{k-1}-1\),这样最后能过岸的就多了一倍

也就是有\((n+1)*2^{k}\)可以过河

\(\mathcal{Code}\)

/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年08月27日 星期二 14时58分07秒
*******************************/
#include <cstdio>
#include <fstream>
#define ll long long
using namespace std;
ll n,k;
int main()
{
	scanf("%lld%lld",&n,&k);
	printf("%lld\n",(k+1)*(1<<n));
	return 0;
}

如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧

posted @ 2019-08-27 19:35  Morning_Glory  阅读(797)  评论(0编辑  收藏  举报
//