洛谷_P1244 [NOI2000]青蛙过河(尚贤)

【题目传送门】

原来A和B也是石墩,青蛙也要按大小排不能一个一个跳过去哇QAQ

既然如此我们用 f[h][k] 表示 h 个石墩 k 片荷叶时最多的青蛙数

显然 f[0][k]=k+1

h=1时,让尽可能多的青蛙跳到D区石墩上(f[0][k]),再让尽可能多的青蛙跳到B石墩上(f[0][k]),最后让D区石墩上的青蛙跳到B上,所以 f[1][k]= f[0][k] + f[0][k]。

h=2时,让尽可能多的青蛙跳到D区的第一个石墩上(f[1][k]),再让尽可能多的青蛙跳到D区的第二个石墩上(f[0][k]),再让尽可能多的青蛙跳到B石墩上(f[0][k]),再让D区第二个石墩上的青蛙跳到B石墩上,最后让D区第一个石墩上的青蛙跳到B上,所以 f[2][k]=f[1][k]+ f[0][k] + f[0][k]。

以此类推。f[h][k]=f[h-1][k]+f[h-2][k]+…+f[1][k]+f[0][k]+f[0][k]

由于青蛙跳到D区石墩上和从D区跳到B上环境是一样的(即空石墩的数量是一样的),所以不用担心青蛙跳不到B上啦。

得到递推公式之后,让我们再来看一看。

f[1][k]= f[0][k] + f[0][k]=2*(k+1)

f[2][k]=f[1][k]+ f[0][k] + f[0][k] =f[1][k]+f[1][k]=22(k+1)

f[3][k]=f[2][k]+ f[1][k]+ f[0][k] + f[0][k]=f[2][k]+f[2][k]=222*(k+1)

… f[h][k]=2f[h-1][k]=(2^h)(k+1)

于是我们得到了通项公式f[h][k] =(2^h)*(k+1)

下面是代码:

#include <iostream>
using namespace std;
int main(){
    int h,k;
    cin>>h>>k;
    cout<<(k+1)*(1<<h);
    return 0;
}

位运算呢是出于省(zhuang)时(bi)的考虑。 还有就是题目中没有给出数据范围,原题中应该是 h<20 , k<1000 来着,所以不用 long long更不用高精度啦。

|-------------------------------------------------------华丽的分隔线--------------------------------------------------------------|
|-------------------------------------------------------华丽的分隔线--------------------------------------------------------------|
|-------------------------------------------------------华丽的分隔线--------------------------------------------------------------|

这题难度其实并不大,真正的代码很短,只是需要正确的解读。

我翻阅了很多题解,发现各位奆佬不屑于解读题目,于是,有了这篇题解

假设dp[i][j]表示i片荷叶j片石墩能通过的青蛙数。

则原题中有这样几个关键点:

石墩可以容纳很多青蛙,但是编号必须从小到大;荷叶只能容纳一只青蛙。换而言之,荷叶只是容纳青蛙,保证青蛙能从小到大的一个载体。荷叶的个数和青蛙的个数决定能有青蛙停留的个数,石墩是青蛙的中转站。
题目中青蛙有无数只,不需要考虑青蛙是否足够。也就是说如果荷叶有k片,青蛙直接从出发点去终止点,则有k只青蛙可以站在荷叶上,还有一只可以站在青蛙出发的A石墩,共有k+1只,(即dp[0][k]=k+1)
假设在出发点和终止点中间有一个石墩C(即原题中说的h=1,也就是dp[1][k]记录的结果)时,青蛙就可以在C点转乘,相当于求蛙从A到C的最多个数,也就是中间没有石墩,k片荷叶的情况,即dp[0][k];当然,一部分青蛙还可以直接转移到终止点,也是dp[0][k]的情况。所以dp[1][k]=dp[0][k]+dp[0][k]=2 dp[0][k]*
假设有两个石墩C,D(即原题中说的h=2,也就是dp[2][k]记录的结果),就比只有一个C点的情况(dp[1][k])多了从C到D,从D到终止点(dp[0][k]+dp[0][k])两种情况。也就是说dp[2][k]=dp[0][k] 2+dp[1][k]=dp[0][k] 2 +dp[0][k] 2 = 2 2 * dp[0][k]
继续探究…
从中不难发现规律:dp[h][k] = dp[0][k] 2 ^ h = (k+1) 2 ^ h (参考第一点)

也就是说,答案最终与dp数组无关。

不难写出如下的代码:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int h,k;
    scanf("%d%d",&h,&k);
    long long ans=0;
    ans=(k+1)*(1<<h);
    printf("%lld\n",ans);
    return 0;
} 

需要关注一下的有一下几点:

1.位运算1<<n表示2^n
2.本蒟蒻的代码和第一篇题解的代码很相似,只是想多解释一下题目的一些细节。

祝各位好运!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值