超级圣诞树(BC115) 【题解】超详细

前言

这个题看了很久,没想出来,然后看了一些大佬的题解(可能是我的理解能力有些慢),中途有很多次放弃的想法,但是最终坚持着 ,研究明白了。

所以想结合我的想法更加具体分享一下

 

题目

描述

今天是圣诞节,牛牛要打印一个漂亮的圣诞树送给想象中的女朋友,请你帮助他实现梦想

输入描述

输入圣诞树的大小 n

1 ≤  n ≤  8

输出描述

输出对应的圣诞树

难度 中等

题目链接  BC 115 超级圣诞树

示例1

输入:

1

输出:

  *
 * *
* * *
  *

说明:

 

示例2

输入:

2

输出:

     *
    * *
   * * *
  *     *
 * *   * *
* * * * * *
     *
     *
说明:
 

示例3

输入:

3

输出:

           *
          * *
         * * *
        *     *
       * *   * *
      * * * * * *
     *           *
    * *         * *
   * * *       * * *
  *     *     *     *
 * *   * *   * *   * *
* * * * * * * * * * * *
           *
           *
           *

说明:

 

 

示例4 

输入:

4

输出:

                       *
                      * *
                     * * *
                    *     *
                   * *   * *
                  * * * * * *
                 *           *
                * *         * *
               * * *       * * *
              *     *     *     *
             * *   * *   * *   * *
            * * * * * * * * * * * *
           *                       *
          * *                     * *
         * * *                   * * *
        *     *                 *     *
       * *   * *               * *   * *
      * * * * * *             * * * * * *
     *           *           *           *
    * *         * *         * *         * *
   * * *       * * *       * * *       * * *
  *     *     *     *     *     *     *     *
 * *   * *   * *   * *   * *   * *   * *   * *
* * * * * * * * * * * * * * * * * * * * * * * *
                       *
                       *
                       *
                       *

说明:

 

 

 

解题的核心思想:  使用二维数组来进行存储图案 

 代码展示

 

#include<stdio.h>
int main() 
{

	//使用二维数组存储圣诞树 
	/*
	* 首先根据规律计算出 二维数组行和列的上限
	* //行的规律是 pow(2,(n-1))*3+n  当n == 8时  row = 392
	* //列的规律是 pow(2,n)*3 - 1    当n == 8时  col = 769
	* //所以进而确定行和列的取值范围
	*/
	int n = 0;
	scanf("%d",&n);
	int arr[400][800] = {{0,0,1,0,0},{0,1,0,1,0},{1,0,1,0,1}};
	int i, j = 0, k, row = 3, col = 5;
	for (i = 2; i <= n; i++)//n>=2时才使用二维数组进行排(方便依次的递增)
	{
		//先进行复制
		for (j = row; j < row * 2; j++)
		{
			for (k = 0; k < col;k++)
			{
				arr[j][k] = arr[j - row][k];//复制为左下方的三角形
				arr[j][k + col + 1] = arr[j][k];//再把左下到复制的,也复制到右下
			}
		}
		//因为最开始的三角形是靠近最左的,清空后再重新置放到左下和右下的中间
		//先清空
		for (j = 0; j < row;j++)
		{
			for (k = 0; k < col;k++)
			{
				arr[j][k] = 0;
			}
		}
		//放到中央(这时需要我们把之前已经复制好的左下三角形复制到中央(当然右下也可以,左下比较方便))
		for (j = 0; j < row;j++)
		{
			for (k = (col+1)/2;k<col+(col+1)/2;k++) //这里的 /2 是为了放置于中间
			{
				arr[j][k] = arr[j + row][k-((col+1)/2)]; //左下复制到中间
			}
		}

		//根据规律和递归思想 ,该树的变化和2次方有关系
		row *= 2;
		col = col*2 +1;//这里的加1是方便为了中间放置三角形
	}


	for (i = 0; i < row; i++)
	{//打印圣诞树
		for (j = 0; j < col; j++)
		{
			if (arr[i][j] == 0)
			{
				printf(" ");
			}
			else
			{
				printf("*");
			}
		}
		printf("\n");
	}

	//打印树柄
	for (i = 0; i < n;i++)
	{
		for (j = 0; j < col / 2;j++)
		{
			printf(" ");
		}
		printf("*\n");
	}
	return 0;
}

 

 题目解析超详细

因为这里的思想是使用二维数组来进行存储图案,然后发现随着输入数字的增大,圣诞树也是有一定规律的增大,这里有点像递归的思想。发现图案是由 一个个3行5列的三角组成的

接下来就进行一步一步来分析:

 

第一步  因为圣诞树的大小为 1- 8,所以我们要考虑二维数组的取值范围 ,避免数组大小不够

 

首先根据图案分析 他们的一次增长的行和列的规律,

分析上述 得到结论  

行数 与 n 的关系 

列数与 n 的关系      

这里我们取 n == 8    行数为 392,列数为 767

 

所以为了避免越界我们取 二维数组的范围  arr[400][800]

第二步 构造那个小三角  给二维数组部分初始化(先初始化一个小三角)【核心】

int arr[400][800] = {{0,0,1,0,0},{0,1,0,1,0},{1,0,1,0,1}};

初始时  3行  5列   

int i, j = 0, k, row = 3, col = 5;

 然后等到打印的时候,数字0表示 " ",数字1表示 ”*“

注意这里的起初三角就是 放在数组最左上方 ,因为根据组成指定的圣诞树,所以这里为了方便先进行 分别复制左下和右下边的三角形  ,然后 再把最左上那个三角形进行 想办法移动到中间。

 

1.把左下角和右下角的三角形复制过去 

		//先进行复制
		for (j = row; j < row * 2; j++)
		{
			for (k = 0; k < col;k++)
			{
				arr[j][k] = arr[j - row][k];//复制为左下方的三角形
				arr[j][k + col + 1] = arr[j][k];//再把左下到复制的,也复制到右下
			}
		}

 

图解

 

2.把最左上的三角先清空(置0),然后再把其重新复制到中间

		//因为最开始的三角形是靠近最左的,清空后再重新置放到左下和右下的中间
		//先清空
		for (j = 0; j < row;j++)
		{
			for (k = 0; k < col;k++)
			{
				arr[j][k] = 0;
			}
		}
		//放到中央(这时需要我们把之前已经复制好的左下三角形复制到中央(当然右下也可以,左下比较方便))
		for (j = 0; j < row;j++)
		{
			for (k = (col+1)/2;k<col+(col+1)/2;k++) //这里的 /2 是为了放置于中间
			{
				arr[j][k] = arr[j + row][k-((col+1)/2)]; //左下复制到中间
			}
		}

 

 如图

 这就是所要打印的图案

(当然必须是n>1)

 

 接着就是按照这样的思想,发现

 

		//根据规律和递归思想 ,该树的变化和2次方有关系
		row *= 2;
		col = col*2 +1;//这里的加1是方便为了中间放置三角形

再以 为基准,当n = 3时 ,制作左下三角,制作右下三角

总结就是这样每一次复制下去 

 然后把图形打印出来

	for (i = 0; i < row; i++)
	{//打印圣诞树
		for (j = 0; j < col; j++)
		{
			if (arr[i][j] == 0)
			{
				printf(" ");
			}
			else
			{
				printf("*");
			}
		}
		printf("\n");
	}

 

 第三步 打印树柄

打印星号的位置就是在 列的 1/2 处打印

	//打印树柄
	for (i = 0; i < n;i++)
	{
		for (j = 0; j < col / 2;j++)
		{
			printf(" ");
		}
		printf("*\n");
	}

 

最后 还是感谢网上大佬无私地分享题解,启发了我,虽然花费很久,但是收获也是很大的。 

 

 

加油! 

  • 71
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 58
    评论
树上选点是蓝桥杯Java题目中的一种类型,通常需要在给定的树结构中选择一个或多个节点作为目标节点,并进行相应的操作。下面是一个简单的树上选点蓝桥Java题解的示例: 题目描述: 给定一棵有N个节点的树,每个节点上都有一个非负整数值。现在需要选择一些节点,使得选择的节点的值之和最大,且所选节点不能相邻(即选了一个节点,则其父节点和子节点都不能选)。请编写一个程序,计算出最大的节点值之和。 解题思路: 这是一个典型的动态规划问题。我们可以定义一个数组dp,其中dp[i]表示以第i个节点为根节点的子树中所选节点的最大值之和。对于每个节点i,有两种情况: 1. 选择节点i:则其子节点都不能选,所以dp[i] = val[i] + dp[grandchild1] + dp[grandchild2] + ... 2. 不选择节点i:则其子节点可以选择或不选择,所以dp[i] = max(dp[child1], dp[child2], ...) 根据以上思路,我们可以使用递归或者迭代的方式来计算dp数组。最终,所求的最大值即为dp,其中1表示根节点。 代码示例: ```java public class TreeSelectPoint { public static void main(String[] args) { int[] values = {0, 1, 2, 3, 4, 5}; // 节点值数组,下标从1开始 int[][] edges = {{1, 2}, {1, 3}, {2, 4}, {2, 5}}; // 树的边关系数组 int n = values.length - 1; // 节点个数 int[] dp = new int[n + 1]; // 动态规划数组 // 构建树的邻接表 List<List<Integer>> adjacencyList = new ArrayList<>(); for (int i = 0; i <= n; i++) { adjacencyList.add(new ArrayList<>()); } for (int[] edge : edges) { int u = edge[0]; int v = edge[1]; adjacencyList.get(u).add(v); adjacencyList.get(v).add(u); } dfs(1, -1, values, adjacencyList, dp); // 从根节点开始进行深度优先搜索 System.out.println(dp[1]); // 输出最大节点值之和 } private static void dfs(int cur, int parent, int[] values, List<List<Integer>> adjacencyList, int[] dp) { dp[cur] = values[cur]; // 初始化当前节点的dp值为节点值 for (int child : adjacencyList.get(cur)) { if (child != parent) { // 避免重复访问父节点 dfs(child, cur, values, adjacencyList, dp); dp[cur] += dp[child]; // 更新当前节点的dp值 } } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 58
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值