牛客网BC115---超级圣诞树(java)
和女朋友坐一块的时候,突然想到了,哈哈哈哈哈
不会很难!!!
import java.util.*;
import java.lang.Math;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
/**
思考过程如下:
小三角形个数为 3^(n-1)
1 3 9 27
3^(1-1) = 1
3^(2-1) = 3
3^(3-1) = 9
3^(4-1) = 27
3^(5-1) = 81
// 去除杆子有多少层 用到了
n
3x1 3 3*2^(1-1)
3x2 6 3*2^(2-1)
3x4 12
3x8 24
3x16 48
int allP = 3 * (int)Math.pow(2, n - 1);
最底层三角形个数 没用到
n
1 1 0+1 2^(n-1)
2 2 1+1
3 4 2+1+1
4 8 4+2+1+1
5 16 8+4+2+1+1
6 32 16+8+4+2+1+1
int lastPT = Math.pow(2, n - 1)
最底层宽度 最底层三角形个数*6 用到了
n
1 6
2 12
3 24
4 48
5 96
int lastPW = (int)Math.pow(2, n - 1) * 6;
24 - 3 - 12 - 0
左边宽 最底层宽度 - 6 / 2 每三行-3 用到了
1 0
2 3-0
3 9-6-3-0
4 21-18-15-12-9-6-3-0
int leftW = (lastPW - 6) / 2;
最底层判断 需要
int nowP = 0;
int lastP = 3;
int checkN = 1;
if nowP = lastP
checkN++;
lastP += lastP
第几层,三角形大间隔 当checkN>2时,存在大间隔 最大间隔等于上一层最底层宽度-6
!!!!用到了!
int triW = 0; // 初始值
if (nowP == lastP) {
checkN++;
lastP += lastP;
if (checkN > 2) {
triW = ((int)Math.pow(2, checkN - 2) - 1) * 6; //<----用到了这个
}
starN = 2; // " * "、" * * "、"* * * "每层数量
starP = 0; // 输出了几层了
}
n
1 0
2 0
3 6-0 每三行-6
4 18-12-6-0
5 42-36-30-24-18-12-6-0
if (nowP % 3 == 0) {
triW -= 6;
leftW -= 3;
}
// " * "、" * * "、"* * * "每层
starN = 2 // " * "、" * * "、"* * * "每层数量
starP = 1 // 输出了几层了
if (starP % 4 == 0) starN *= 2;
// 星与星间距
2 2 2 3 3*1
4
4 4 4 6 3*2
4 4 4 9 3*3
10
8 8 8 12 3*4
8 8 8 15 3*5
16
16 16 16 18 3*6
16 16 16 21 3*7
22
32 32 32 24 3*8
int starW = (lastPW - starN * 6 - leftW - triW) / 2;
24 - 12 - 3 - 6
*/
/*
观察例子,可以发现,从n=2开始
左右树两边都是前者各层的形状,故直接计算好整体左边和左右两边树间距即可实现了
*/
int n = in.nextInt();
int lastPW = (int)Math.pow(2, n - 1) * 6; // 最底层宽度
int leftW = (lastPW - 6) / 2; // 左边宽 每三层-3
int allP = 3 * (int)Math.pow(2, n - 1); // 去除杆子的总层数
int checkN = 1; // 检测n,每个n对应的层数
int starW = 0; // 左右两边间距
int starP = 0; // 统计每新的开始输出几层了
String[] treeData = new String[allP + n]; // 树
for (int i = 1; i <= allP; i++) {
for (int j = 0; j < leftW; j++) System.out.print(" "); // 输出左边宽
if (i < 4) { // 相当于一个初始化的过程
String putStr = "";
if (i == 1) {
// " * "
putStr = " * ";
} else if (i == 2){
// " * * "
putStr = " * * ";
} else {
// "* * * "
putStr = "* * * ";
}
treeData[i - 1] = putStr;
System.out.print(putStr);
} else { // 开始输出前者的内容
StringBuilder putStr = new StringBuilder();
for (int j = 0; j < 2; j++) { // 左右
putStr.append(treeData[starP]);
if (j == 0) {
// 输出间距
for (int k = 0; k < starW; k++) {
putStr.append(" ");
}
}
}
System.out.print(putStr);
treeData[i - 1] = putStr.toString();
}
System.out.println();
starP++;
if (i % 3 == 0) { // 每三层,左边宽度-3,左右两边树的间距-6
leftW -= 3;
starW -= 6;
}
// 根据checkN知道当前输出是否到达每个n所处的输出范围
if ((int)Math.pow(2, checkN - 1) * 3 == i) {
checkN++;
starP = 0; // 每个n(checkN),就是新的开始
if (checkN > 2) {
starW = (int)Math.pow(2, checkN - 2) * 6 - 6; // 左右两边树的间距计算
}
}
}
// 杆子
int leftTW = (lastPW / 2) - 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < leftTW; j++) {
System.out.print(" ");
}
System.out.println("*");
}
}
}
下面附图进一步理解:
最后,感谢你阅读我的文章,感恩!!!