P1244 青蛙过河

P1244 青蛙过河
NOI2000
主要思想:
数学归纳法 递推 压位高精度 化归
理解能力和找规律的能力
题意再述:
1.青蛙从上到下必须连续递增或者下面是石墩
而不能是
1 1
2 3
3 4
而且每时每刻都要满足这个条件
2.左岸和右岸都是石堆
公式推导过程:
k=0
h=0 s=1
h=1 s=2 _ _ _
h=2 s=?

当h=1时,共有三个石墩,空石墩有2个,我们可以转移2个青蛙到任意石墩
当h=2时,总石墩数比原来多1,空石墩有3个,我们可以先利用3个空石墩把上面2个小青蛙(1号和2号)移到一个非右岸的一个空石墩上,现在共有2个空石墩,由h=1时
(空石墩有2个,我们可以转移2个青蛙到任意石墩)
,我把下面两个大青蛙,移到右岸,再把,小青蛙移到右岸。完成。

假设当h=x,k=0时,空石墩有x+1个,最多能转移的青蛙数为(1<<x)
当h=x+1时,k=0,空石墩有x+2个,我们可以利用x+1个空石墩把(1<<x)个青蛙移到一个非右岸的一个空石墩上,现在有空石墩h+1个,我们用这x+1个空石墩将下面的(1<<x)个大青蛙移到右岸,现在还是有空石墩x+1个,再用这些把刚才的(1<<x)个小青蛙移到右岸。移动的青蛙总数是h=x时的两倍,故为
(1<<(x+1));
所以当k=0时,转移的青蛙数为(1<<h)

要是k>0呢?

我们知道,当k=0时,转移的青蛙数为(1<<h),单个青蛙可以直接移动,我们把(k+1)只青蛙压成一只青蛙,因为(k+1)只青蛙可以像一只青蛙一样直接移动,why?先把k只青蛙放到k个荷叶上,再把最下面的那只移到目标位置,再把荷叶上的k只青蛙移到最下面的那只上就可以不借助石墩实现(k+1)只青蛙的直接移动。
原来当k=0时,转移的青蛙数为(1<<h),现在把(k+1)只青蛙压成一只青蛙,所以总数为:
(1<<h)*(k+1)

结束了???
完美了???

但是这样只是证明了这种解的存在性,并没有证明最优性。有想法的和我继续讨论。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<ctime>
 7 #include<cstring>
 8 #define inf 2147483647
 9 #define For(i,a,b) for(register long long i=a;i<=b;i++)
10 #define p(a) putchar(a)
11 #define g() getchar()
12 //by war
13 //2017.10.19
14 using namespace std;
15 long long h,k;
16 void in(long long &x)
17 {
18     long long y=1;
19     char c=g();x=0;
20     while(c<'0'||c>'9')
21     {
22     if(c=='-')
23     y=-1;
24     c=g();
25     }
26     while(c<='9'&&c>='0')x=x*10+c-'0',c=g();
27     x*=y;
28 }
29 void o(long long x)
30 {
31     if(x<0)
32     {
33         p('-');
34         x=-x;
35     }
36     if(x>9)o(x/10);
37     p(x%10+'0');
38 }
39 int main()
40 {
41     in(h),in(k);
42     cout<<((1<<h)*(k+1));
43      return 0;
44 }
View Code
原文地址:https://www.cnblogs.com/war1111/p/7690552.html