Featured image of post 弹珠堆放-蓝桥杯

弹珠堆放-蓝桥杯

1456 字

弹珠堆放 - 17142


题目:

小蓝有 20230610 颗磁力弹珠,他对金字塔形状尤其感兴趣,如图:

题目

  • 高度为 1 的金字塔需要 1 颗弹珠
  • 高度为 2 的金字塔需要 4 颗弹珠
  • 高度为 3 的金字塔需要 10 颗弹珠
  • 高度为 4 的金字塔需要 20 颗弹珠

小兰想知道用他手里的弹珠可以摆出的最高金字塔高度是多少?


解题思路

这个题目大概就是给定一个序列经过公式计算求最大值。如果觉得题目给的数字太大了可以把总数量缩小为 20 个,就是题目上说的 4 层总数为 20。首先要把已知条件列出来:

第 1 层:1
第 2 层:4
第 3 层:10
第 4 层:20

所以序列是 [1, 4, 10, 20],如果觉得看这个序列没头绪那就把前面的层数加进来看有无规律。

规律:第一层是 1 个弹珠,第二层总数为 4 个,那么第二层就是要 3 个,可以写出来:

第一层 : 1

第二层 : 3

那题目给的 4 就是 1+3 得来的,那么这两层之间的规律可以看出第一层需要弹珠的数量 (1) + 第二层的层数 (2) 就是第两层需要的弹珠数量。

那么一个简单的公式:第 n 层需要的弹珠数量 + 第 n+1 的层数 = 第 n 层需要的弹珠数量。

所以就得出要定义两个变量(高度和当前层的弹珠数量)一个常量(总数量):

规律如图:

金字塔高度 总弹珠数 各层珠分布
1 1 1
2 4 1 + 3
3 10 1 + 3 + 6
4 20 1 + 3 + 6 + 10
1
int sum = 20; int high = 1; int cnt = 1;

”定义完变量和常亮后就要进行循环了,但是我们不知道循环多少次,也不知道什么时候结束,有一个口诀:``知道次数用 for,否则用 while,所以就要用 while`

进入 while 循环后要先把当前层的弹珠减去,所以就是 sum -= cnt;

1
2
3
while (true) {
    sum -= cnt;
}

然后再把 high++,因为层级增加嘛,加完高度后就要想那个公式怎么用了,我们可以带入一个值,按照定义的初始值带进去就编程 sum -= 1 --> 19, high++ --> 2,现在下一个层级有了,上一层需要的弹珠数量有了,两者相加即可:cnt += high; 可以带入值 1(第一层需要的弹珠数量)和 2(第二层),1+2=3 是第二层需要的弹珠数量。

1
2
3
4
5
while (true) {
    sum -= cnt;
    high++;
    cnt += high;
}

现在都求完后就要输出了,但是输出不可能直接输出,如果直接在循环外写输出,那循环就压根不会到循环外的输出语句,

1
2
3
4
5
6
7
8
// 错误示例
while (true) {
    sum -= cnt;
    high++;
    cnt += high;
}
// 写在循环外压根执行不到这里,并且循环式死循环,因为没有停止条件。
System.out.println(high);

如果写循环里面可以输出,无论写在哪里都会报错,因为判断条件永远为真,最后会死循环一直执行

1
2
3
4
5
6
7
8
9
// 错误示例
while (true) {
    sum -= cnt;
    // 或者放这:System.out.println(high);
    high++;
    // 再或者放这:System.out.println(high);
    cnt += high;
    System.out.println(high);
}

所以还要给输出添加前置判断条件:假如总数量 = 0 的时候输出 high,但是这时候问题又出现了:假如最后 sum - cnt 成负数了就不输出了吗?显然不可能,我们还要再加一个判断条件:当 sum < 0 的时候 high 就要 -1。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 错误示例
while (true) {
    sum -= cnt;
    // 为什么在这里判断?因为上面是执行完事剩余的数量,如果都不成立那就继续执行下面的两句代码。
    if (sum < 0) {
        System.out.println(high - 1);    
    } else if (sum == 0) {
        System.out.println(high);
    }
    high++;
    cnt += high;
}

如果你觉得写到这里就 结束 了那就错了,如果写到这里可以运行试下:显然结果是死循环。

错误截图

因为他会一直执行 high++;cnt += high;,所以我们还要给每一个判断加上 break; 结束语句,这样才算真正完成。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
int sum = 20; int high = 1; int cnt = 1;
while (true) {
    sum -= cnt;
    if (high < 0) {
        System.out.println(high - 1);
        break;
    } else if (high == 0) {
        System.out.println(high);
        break;
    }
    high++;
    cnt += high;
}

正确截图

把这个程序写出来后那最后把 sum 的值改成题目要求的 20230610 就行了。

最终代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int sum = 20230610;
        int high = 1;
        int cnt = 1;
        while (true) {
            sum -= cnt;
            if (sum < 0) {
                System.out.println(high - 1);
            } else if (sum == 0) {
                System.out.println(high);
            }
            high++;
            cnt += high;
        }
    }
}
本博客已稳定运行 0
发布了 9 篇文章 | 共 8.8K
Hugo 主题 Stack 由Jimmy设计
Chiba
...