牛客网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("*");
        }

    }
}

 

下面附图进一步理解:

牛客网BC115---超级圣诞树(java)

 

 

 

最后,感谢你阅读我的文章,感恩!!!

 

原文链接:https://www.cnblogs.com/skypeng/p/17320362.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:牛客网BC115—超级圣诞树(java) - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • Java多线程之线程的创建

    Java是一门拥有多线程机制的语言,它的多线程编程是Java编程中必须掌握的重要内容,本文将详细讲解Java多线程之线程的创建。 线程的创建方式 Java中线程的创建主要有以下两种方式: 继承Thread类 继承Thread类是Java中最基本的一种创建线程的方式,创建一个线程类需要继承Thread类,并重写run方法。在run方法中编写线程需要执行的任务,…

    Java 2023年5月26日
    00
  • struts2与cookie 实现自动登录和验证码验证实现代码

    实现自动登录和验证码验证是网站开发中比较常见的需求。在 Struts2 中,可以通过 Cookie 实现自动登录,在用户下次访问网站时,可以直接读取 Cookie 中的登录信息,将用户登录状态自动恢复。验证码则是为了保证网站的安全性,防止自动化程序暴力攻击登录页面。下面介绍基于 Struts2 框架的自动登录和验证码验证的实现方法。 自动登录实现方法 在用户…

    Java 2023年5月20日
    00
  • tk-mybatis整合springBoot使用两个数据源的方法

    下面是“tk-mybatis整合springBoot使用两个数据源的方法”的完整攻略及两条示例: 一、准备工作 在进行整合之前,我们需要做以下准备工作: 创建两个数据库,分别为db1和db2,并分别创建表user,表结构如下: CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name`…

    Java 2023年5月20日
    00
  • 浅谈Java中ArrayList线程不安全怎么办

    针对“浅谈Java中ArrayList线程不安全怎么办”,我为您提供以下攻略: 一、线程不安全的原因 在 Java 中,ArrayList 是一个非线程安全的集合类。这是因为在集合中,元素的增加或者删除可能涉及到内部数组的扩容或缩容等操作,而这些操作可能会导致多个线程同时访问同一个 ArrayList 实例,产生线程安全问题。 二、解决方案 为了解决这个问题…

    Java 2023年5月26日
    00
  • java lambda循环_使用Java 8 Lambda简化嵌套循环操作

    下面是关于Java 8 Lambda简化嵌套循环操作的攻略: 1. lambda表达式简介 Java 8引入了lambda表达式,它是一种匿名函数,可以像参数一样传递给方法或赋值给变量。在使用lambda表达式时只需要关注其输入和输出,而不必关心具体的实现细节,这让代码变得更加简洁易读。 2. 简化循环操作 在Java 8之前,嵌套循环操作可能会使代码显得冗…

    Java 2023年5月26日
    00
  • mybatis的使用-Mapper文件各种语法介绍

    下面是关于mybatis的使用-Mapper文件各种语法介绍的完整攻略: 1. Mapper文件介绍 Mapper文件是mybatis中核心的配置文件之一,它用于将SQL语句映射到Java代码中的方法上。Mapper文件位于src/main/resources目录下,除了在其中定义SQL语句之外,还可以在其中定义各种参数、返回值类型、条件语句、循环语句等等。…

    Java 2023年5月20日
    00
  • jsp页面显示数据库的数据信息表

    下面是如何在JSP页面中显示数据库的数据信息表的完整攻略。 第一步:连接数据库 在JSP中连接数据库需要使用JDBC驱动程序。我们可以使用以下代码来连接MySQL数据库。 <%@ page import="java.sql.*" %> <% Connection con = null; Statement stmt = …

    Java 2023年6月15日
    00
  • java 使用策略模式操作JDBC数据库

    使用策略模式操作JDBC数据库 什么是策略模式 策略模式是一种行为设计模式,它可以让你定义一系列的算法,将这些算法封装起来并且可以相互替换。策略模式让算法的变化独立于使用算法的客户端(调用者)。本质上来讲,策略模式是一种用来管理过多相似类的经典方法,使用策略模式可以避免使用大量的if语句。 策略模式在Java中的应用 在Java中,我们可以使用策略模式对JD…

    Java 2023年6月16日
    00
合作推广
合作推广
分享本页
返回顶部