小兔蹦蹦跳【脑洞】

题目描述

小兔位于X轴的x点,欲跳至X轴的y点。x,y均为整数。小兔每次沿x轴直线跳跃,每跳的长度均为正整数,假设

小兔一共跳了n次才到目的地,每次跳的长度为F1,F2,..., Fn. 有规则如下:

F1=Fn=1

|Fi-Fi-1|<=1   , 2<=i<=n         (注:| |是绝对值符号)

我们的问题是给定x,y, 如何使得n最小。

输入

包含多组数据,但不超过1000组。每组数据一行,每行包括两个整数x和y。0 <= x < y <= 1000000000 。

输出

对于每一组数据,输出一行,即从x到y的最小跳跃次数n。

样例输入

45 4845 4945 50

样例输出

334

这道题出的非常好,我一点思路也没有。

先理解清楚题意,第一步和最后一步都只能跳1,且相邻跳跃次数相差不能大于1

我觉得画个草图能好理解点:

图上格子高度代表一次跳跃的长度,那么列格子数量就代表跳了几次,显然这样格子的总面积代表跳跃的距离。这样画的好处就是能很好看出第一步和最后一步只跳1。f(n)代表最高格子为按上图形式跳时的跳跃距离,其实还需要用到f(n)的递推式。

    即f(n)=f(n-1)+n+n-1=f(n-1)+2n-1。而且n对应的跳跃次数为2n-1。

这样或许就好理解点了,想想看,上图是最对称最完美的跳跃方式,跳跃距离还都是平方数(感觉挺神奇的)。f(n)与f(n-1)差2n-1,也就是在f(n-1)~f(n-1)+2n-1的范围内都是n-2是最大的跳跃数。用个例子说明一下:

    比如f(4)=16,f(3)=9。当距离为10时,9<10<16,易知此时“最高峰(最高的格子)“只能到3,而f(3)=9,还差1,那么好办,只需在高度为1的格子旁边再放一个高度为一的格子就能满足要求,这样也会多跳一回,所以最小跳跃次数就为(10-9)+2*3-1=6;

而当距离为15时,15-9=6>3,显然,这比“最高峰“还要大,所以一次是跳不完的,那就跳两次,也就是在高度为3的格子旁放置两个高度为3的格子。当距离再大时,最高的格子就应该为4了,问题又可以同样处理了。因此得到问题的答案:

    

(pos相当于上述n,len为距离)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <map>
 4 #include <climits>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <algorithm>
 8 #include <cmath>
 9 using namespace std;
10 typedef long long LL;
11 const int maxn=1e9+10;
12 int a[100050];
13
14 int main()
15 {
16     a[1]=1;
17     for(int i=2;;i++){
18         if(i*i>maxn) break;
19         a[i]=i*i;
20     }
21     int s,t;
22     while(scanf("%d%d",&s,&t)==2)
23     {
24         int len=t-s;
25         int pos=1;
26         for(int i=1;;i++){
27             if(a[i]>len&&a[i-1]<=len){
28                 pos=i-1;
29                 break;
30             }
31         }
32         len-=a[pos];
33         int ans=2*pos-1;
34         if(!len) printf("%d\n",ans);
35         else if(len<=pos) printf("%d\n",ans+1);
36         else printf("%d\n",ans+2);
37     }
38     return 0;
39 }

思路来源:

http://blog.csdn.net/qq_31138083/article/details/51236696

时间: 2024-10-06 00:53:36

小兔蹦蹦跳【脑洞】的相关文章

一对幼兔一个月长成小兔,再过一月长成成兔并生下幼兔,问24个月之后有多少对兔子,成兔每个月都会生下一对幼兔

int a=1,b=0,c=0,sum = 0;//a 幼兔对数,b 小兔对数,c 成兔对数,sum 总对数 for (int i = 1; i <=24; i++) { if (i == 1) { a = 1; b = 0; c = 0; } else { c = b + c; b = a; a = c; } sum = a + b + c; Console.WriteLine(i+"个月后,一共有兔子" + sum + "对,其中幼兔" + a + &qu

小兔的棋盘(hdu2067)

小兔的棋盘 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7547    Accepted Submission(s): 4020 Problem Description 小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望.不过没过几天发现了棋盘的好玩之处.从起点(0,0)走到终点(

HDU2067 小兔的棋盘【DP】

小兔的棋盘 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6922    Accepted Submission(s): 3708 Problem Description 小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望.不过没过几天发现了棋盘的好玩之处.从起点(0,0)走到终点(

一对幼兔一个月后长成小兔(每对兔子默认一公一母),再过一个月长成成兔并且生下一对幼兔,以此类推,两年后有多少兔子

int a = 1; int b = 0; int c = 0; for (int i = 1; i <= 24; i++) { if (i == 1) { a = 1; b = 0; c = 0; } else { c = b + c; b = a; a = c; } Console.WriteLine("幼兔{0},小兔{1},大兔{2},总数{3}",a,b,c,(a+b+c));

例题:一对幼兔,一个月后长成小兔,小兔一个月后长成成兔并生下一对幼兔,问n个月后有多少对兔子。这个题主要是学习计算机思维,我们只需要把条件告诉计算机,让计算机算结果

static void Main(string[] args) { //    本月的成兔=上月的小兔+上月的成兔        //    本月的小兔=上月的小兔        //    本月的幼兔=本月的成兔 Console.WriteLine("请输入月数:"); int m = Convert.ToInt32(Console.ReadLine()); int ct = 0;//成兔对数 int xt = 0;//小兔对数 int yt = 1;//幼兔对数 int zt =

杭电---2067 小兔的棋盘

Problem Description  小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望.不过没过几天发现了棋盘的好玩之处.从起点(0,0)走到终点(n,n)的最短路径数是C(2n,n),现在小兔又想如果不穿越对角线(但可接触对角线上的格点),这样的路径数有多少?小兔想了很长时间都没想出来,现在想请你帮助小兔解决这个问题,对于你来说应该不难吧! Input 每次输入一个数n(1<=n<=35),当n等于-1时结束输入. Output 对于

小兔的棋盘

小兔的棋盘 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6748 Accepted Submission(s): 3634 Problem Description 小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望.不过没过几天发现了棋盘的好玩之处.从起点(0,0)走到终点(n,n)的最

HDU2067小兔的棋盘

Description 小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望.不过没过几天发现了棋盘的好玩之处.从起点(0,0)走到终点(n,n)的最短路径数是C(2n,n),现在小兔又想如果不穿越对角线(但可接触对角线上的格点),这样的路径数有多少?小兔想了很长时间都没想出来,现在想请你帮助小兔解决这个问题,对于你来说应该不难吧! Input 每次输入一个数n(1<=n<=35),当n等于-1时结束输入. Output 对于每个输入数据输出路

有一对幼兔,幼兔1个月后长成小兔,小兔1个月后长成成兔并生下一对幼兔,问几年后有多少对兔子,幼兔、小兔、成兔对数分别是多少。

Console.WriteLine("请输入经过了几个年:"); int n = Convert.ToInt32(Console.ReadLine()); int syt = 1, byt = 0; int sxt = 0, bxt = 0; int sdt = 0, bdt = 0; for (int i = 1; i <= n; i++) { byt = sdt + sxt; bxt = syt; bdt = sdt + sxt; syt = byt; sxt = bxt;