UVA846 Steps

一個人沿著一數線前進。他每次走的長度(整數)必須是正的,而且比上一步走的長度多1,一樣,或少1。另外請注意:第一步及最後一步的長度一定是1.

請問這個人若要從x走到y,最少需要走幾步。

舉例說明:若x=45, y=50,那麼每步走的長度可以是:1,2,1,1,所以最少需要4步。

Input

輸入的第一列有一個正整數代表以下有幾組測試資料。每組測試資料一列,含有2個整數x,y(0 <= x <= y < 231)。

Output

每組測試資料輸出一列,最少需要走幾步才能從x走到y。

Sample Input

3
45 48
45 49
45 50

Sample Output

3
3
4

找出步數與距離的關係即可得解。

  • 0步最多能抵達的距離是0
  • 1步最多能抵達的距離是1(1)
  • 2步最多能抵達的距離是2(1 1)
  • 3步最多能抵達的距離是4(1 2 1)
  • 4步最多能抵達的距離是6(1 2 2 1)
  • 5步最多能抵達的距離是9(1 2 3 2 1)
  • 6步最多能抵達的距離是12(1 2 3 3 2 1)
  • ……以此類推

 

题意:在给出的两个数A,B,找出最少需要几步可以从A到B,规则:第一步和最后一步必须是1,还有中途只可以比前一数大一,等于,或小一。。

第一种方法:从A,B开始依次加,然后距离减去步长,直到 dis<0 ,我们可以肯定的是,小于零的这部分C,一定小于当前的步长N,所以我们一定能在之前的步长中找到(N-C),也就可以填满这一部分。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
 
int n;
 
int main()
{
    int t;
    scanf("%d",&t);
    while (t--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        int dis = b - a ;
        bool flag = false ;
        int count = 0 ;
        int step = 1 ;
        while (dis > 0 )
        {
            dis -= step;
            count++;
            if (flag)
                step++;
            flag = !flag;
        }
        printf("%d\n",count);
    }
    return 0;

第二种方法:1+2+…..+(n-1)+n+(n-1)+….2+1 =n^2,这是我们在达到和为n^2在满足题意的情况下能确定的最少步数,设想我们如果 dis==n^2 ,那结果就显而易见了,当dis > n^2的时候,首先我们先确定最大的n满足 n^2 <= dis ,然后我们只要再找dis-n^2的数就可以,如果dis-n^2<=n,那只要再找一个,如果>n,但我们发现这个数一定<(n+1)^2-n^2

,那这个数一定可以化为数列中的两个数。。。

/*
Author:ZCC;
Solve:
// 所走步数对应的序列如果左右对称,那么所走的步数应该是最少的。因为最先一步和最后一步长度均必须是
// 1,又由于每一步的长度必须是非负整数,且要么比上一步步长恰好大 1,要么相等,要么小 1,则左右对
// 称的序列能在最少步数得到最大距离。如果采取左右对称的走法,设两点距离为 distance,n = sqrt
// (distance),则由于最大步数为 n 步时能达到的距离是 1 + 2 + 3 + ... + (n - 1) + n +
// (n - 1) + ... + 3 + 2 + 1 = n^2。比较两点距离 distance 与 n^2,若相等,表明只需走
// 2 * (n - 1) + 1 = 2 * n - 1 步,否则若剩余距离 distance - n^2 在 1 - (n + 1),
// 只需插入一步即可,若 distance - n^2 大于 (n + 1),则需多插入两步即可。
*/

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
 
int main()
{
    int t ;
    scanf("%d",&t);
    while (t--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        int dis = b - a ;
        if (dis <= 3)
            printf("%d\n",dis);
        else
        {
            
            int n = sqrt(dis);
            if ( n * n == dis)
                printf("%d\n",2*n-1);
            else if ((dis-n*n)<=n)
                printf("%d\n",2*n);
            else  printf("%d\n",2*n+1);
        }
    }
    return 0;
}

列出几项,找到规律:

1: 1
2 1 1
3 1 1 1
4: 1 2 1
5 1 2 1 1
6 1 2 2 1
7 1 2 2 1 1
8 1 2 2 2 1
9: 1 2 3 2 1
10 1 2 3 2 1 1
11 1 2 3 2 2 1
12 1 2 3 3 2 1
13 1 2 3 3 2 1 1
14 1 2 3 3 2 2 1
15 1 2 3 3 3 2 1
16: 1 2 3 4 3 2 1

可以得出 n * n : 2 * n – 1

综合得出:

n * n: 1……n……1 minstep: 2 * n – 1.

n * ( n + 1 ) 1…..n,n…….1 minstep: 2 * n

(n + 1) * ( n + 1 ) :1……n+1………1 minstep: 2 * n + 1

代码:

#include <stdio.h>
#include <math.h>
 
int main()
{
    int ncase;
    scanf("%d", &ncase);
    while (ncase--)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        x = y - x;
        if (x == 0)//debug
            printf("0\n");
        else
        {
            y = (int)sqrt(x);
            if (x == y * y)
            {
                printf("%d\n", 2 * y - 1);
            }
            else if (x <= y * (y + 1))
            {
                printf("%d\n", 2 * y);
            }
            else
            {
                printf("%d\n", 2 * y + 1);
            }
        }
    }
    return 0;
}

 

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注