尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

蓝桥杯六芒星打印题:从坐标规律到循环实现

蓝桥杯六芒星打印题:从坐标规律到循环实现 蓝桥杯的“打印图形”题近几届几乎隔年就出一次。今天聊其中一道很有代表性的——六芒星。题目本身不复杂一般形式是输入一个整数 n用*号打出一个由两个三角形叠起来的六芒星图案。很多人第一次看到它容易一头扎进循环里反复改最后图形歪了也不知道错在哪。其实这类题有个固定套路先把图案当二维坐标网格来看再找行列之间的偏移规律最后用两层循环把点打出来。我当年备赛时第一次做这种题也是硬凑空格凑到头晕。后来总结出一套自己的方法不急着写代码先在稿纸上把图形画出来把每一行的星号位置标成坐标找相邻行之间的关系。一旦找到“偏移量”的表达式代码就是水到渠成的事。这篇文章我会从题目拆解、规律推导、代码实现到常见坑位完整讲一遍六芒星打印题的解法。无论你用的是 Java、C 还是 Python核心思路都一样。1. 题目理解与整体设计思路1.1 蓝桥杯打印图形题到底在考什么蓝桥杯的打印图形题表面上是“输出一个由字符组成的形状”实际上考的是两层能力第一层是坐标抽象第二层是循环控制。坐标抽象的意思是把图案放到一个虚拟的二维坐标系里。输出区域可以看成一张网格纸每个字符占据一个格子。你要做的就是决定哪些格子放*哪些格子放空格。不要一上来就想着“我要画一个六芒星”而要想“对于第 row 行第 col 列的格子我该怎么判断它是否该显示星号”。循环控制则是把上面的判断翻译成代码。一般套路是用外层循环控制行内层循环控制列。关键点在于内层循环的边界不一定是固定的可能要根据行数变化也可能要提前终止避免输出多余的行尾空格。我见过很多同学在这类题目上翻车不是因为不会写循环而是因为图没画明白就开始敲代码。你在脑子里觉得图形是“一个三角形加一个倒三角形”但代码里没有“三角形”这个概念只有行号、列号、边界条件。所以第一步永远是先把图形落到坐标上。1.2 典型题设与样例规律为了防止题目定义不清我先给出一种最常见的题设后文全部围绕它展开输入一个正整数 n输出一个高度为2n-1、宽度为2n-1的六芒星轮廓。当 n4 时输出如下* * * * * * * * * * * *这个图形你要仔细看几秒。它其实不是传统的“六角星”而是两个三角形骨架上下对拼上半部分是一个正三角形的两条斜边下半部分是一个倒三角形的两条斜边。竞赛题里有时把这种简化画法直接叫六芒星大家不必在几何定义上纠结做题时以题目给出的样例为准。我们先只看上半部分也就是前 4 行* * * * * * *以 0 开头编号行号第 0 行星号在中间第 1 行有两个星号分别向左、向右各移一格第 2 行继续向两边扩展第 3 行扩展到了最左和最右。所以上半部分是一个“逐渐张开”的过程。再看下半部分从第 4 行开始* * * * *这是上半部分的镜像也就是“逐渐收拢”的过程。所以整个规律其实非常清晰每一行最多只有两个星号它们关于中心列对称。距离中心越远两个星号间隔越大。我们可以把两个星号的位置分别称为左边界left和右边界right那么它们满足left mid - d right mid d其中mid n - 1是中心列的编号d是当前行距离中心行的偏移量。1.3 用表格验证规律为了让你更直观地看到规律我把 n4 时每一行的关键数据列成表格行号 row对称偏移 dleftright星号位置0033中心一个1124第2、4列2215第1、5列3306第0、6列4215第1、5列5124第2、4列6033中心一个你发现没有d的取值是先增后减从 0 到n-1再回到 0。这就是图形上下对称的原因。只要能把d和行号row的关系找出来这道题就解决了一大半。2. 核心细节解析从坐标规律到循环实现2.1 建立坐标系把图形当成二维网格我们用一个行号row和一个列号col来定位每一个字符。行的范围是0到2n-2列的范围理论上也是0到2n-2但实际输出时每一行的最后一个有效字符位置是right不需要输出后面的空格。中心列mid n - 1代表图形的对称轴。如果某一行的星号偏移量为d那么左星号在mid - d右星号在mid d。这里要注意当d 0时左星号和右星号是同一个位置所以这一行只会出现一个*而不是两个。写代码时如果同时判断col left || col right同一个位置也只会输出一次不会重复因为col在循环里只会经过一次。你可能会问为什么列号范围是0到2n-2而不是1到2n-1都可以看你习惯。蓝桥杯的判题系统只关心输出字符内容不关心你是从 0 开始还是从 1 开始。但从 0 开始有一个好处mid正好是n-1偏移后的mid - d和mid d不会出现负数。2.2 偏移量 d 的推导上下对称是关键图形的高度是2n-1中心行是row n-1。在中心行以上或者说row n-1时行越往下偏移量越大偏移量就等于当前行号d row在中心行以下行越往下偏移量越小。从最底部往回看底部第0行也就是实际最后一个字符行偏移量为0往上第1行偏移量为1。所以如果当前行号是row距离底部还有(2n-2 - row)行那么偏移量就是d (2n - 2) - row用条件表达式合并一下就是d row n-1 ? row : (2n - 2) - row你可以代入表格验证一下当row5时d2当row6时d0没问题。这个公式是整个代码最核心的部分。很多人的代码写错就是因为在处理下半部分时把对称关系搞反了。记住一句话上半部分看“已经走了多少行”下半部分看“还剩多少行到底部”。2.3 空格与行尾的处理细节代码里输出空格也有讲究。我推荐的做法是内层循环从col 0一直走到col right遇到left或right就输出*其他位置输出空格。这样循环到right就停止天然不会在行尾留下一串空格。如果你用整行宽度2n-1来循环然后最后统一trim技术上也可以但不是所有在线评测系统都能接受你的字符串尾部处理方式。有些系统用System.out.print逐字符输出多余的尾随空格可能会被当成答案的一部分导致格式错误。另外还有一个容易忽略的点当n1时图形只有一行一个*。按照公式h1mid0row0d0leftright0循环从 0 到 0 输出一个*没有问题。所以这道题不需要单独特判n1公式天然覆盖了边界情况。3. 实操过程与代码实现3.1 Java 实现蓝桥杯最常用的语言蓝桥杯的 Java 组要求主类名为Main并且不能带package。这道题完整代码可以参考下面这样import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc new Scanner(System.in); int n sc.nextInt(); int h 2 * n - 1; int mid n - 1; for (int row 0; row h; row) { int d row mid ? row : h - 1 - row; int left mid - d; int right mid d; StringBuilder sb new StringBuilder(); for (int col 0; col right; col) { if (col left || col right) { sb.append(*); } else { sb.append( ); } } System.out.println(sb.toString()); } } }这里用StringBuilder是为了减少频繁的System.out.print调用。蓝桥杯的输入规模通常不大直接print也能过但养成每次输出整行的习惯对后续做大矩阵题目有好处。代码里d row mid ? row : h - 1 - row和前面的公式等价。h-1-row就是(2n-2)-row。你可以看到整个实现把图形拆成“行号到偏移量”的映射剩下的就是简单的列循环。3.2 C 和 Python 的对照实现C 版本的思路完全一样只是语法不同#include iostream using namespace std; int main() { int n; cin n; int h 2 * n - 1; int mid n - 1; for (int row 0; row h; row) { int d row mid ? row : h - 1 - row; int left mid - d; int right mid d; for (int col 0; col right; col) { if (col left || col right) { cout *; } else { cout ; } } cout endl; } return 0; }Python 版本用列表保存每一行字符最后再join效率也不错n int(input()) h 2 * n - 1 mid n - 1 for row in range(h): d row if row mid else h - 1 - row left mid - d right mid d line [] for col in range(right 1): if col left or col right: line.append(*) else: line.append( ) print(.join(line))这三种语言的解题逻辑完全一致区别只在 IO 和字符串拼接方式。比赛时你用最熟练的语言写就行关键是脑子里的规律不变。3.3 如何快速测试自己的输出写完代码别急着交先用几个小 n 测试。n2 时输出应该是* * * *n3 时输出应该是* * * * * * * *如果你看到中间行是最宽的那一行而且上下完全对称基本就对了。也可以用眼睛目测把输出保存成 txt 文件用文本编辑器打开观察每一行前面空格和*的排列是否呈漂亮的三角形骨架。我在本地测试时会额外写一个简单脚本把输出中的空格替换成点号再来检查...* ..*.* .*...* *.....* .*...* ..*.* ...*这样更容易看出空格的数量是否均匀特别是在终端里空格显示不明显的时候。4. 常见问题与排查技巧4.1 最容易踩的五个坑我把实际做题时容易踩的坑整理成表格方便你对照排查问题原因解决方法图形左右不对称left和right公式写反检查left mid - d和right mid d下半部分偏移方向反了中心行以下的d用成了row用h - 1 - row即“离底部还有多少行”中间行多了一个星号没有处理left right的情况用 行尾有一堆空格内层循环跑到整行宽度h循环上限改为right写到右星号就停图形整体偏左或偏右mid计算错误确认mid n - 1不是n也不是(h-1)/2很多同学会在中间行多输出一个*是因为他们用if (col left) ... if (col right) ...两个独立判断当left right时同一个位置输出两次。实际如果用else if或||就不会有这个问题。4.2 用对称性自查代码打印图形题有一个天然优势结果可以自查。只要你的代码写了两种对称就应该在输出中体现出来。第一种对称是左右对称每一行最左侧星号到中心列的距离等于最右侧星号到中心列的距离。第二种对称是上下对称第i行和第h-1-i行完全相同。你可以在代码里临时加一个断言把每一行存入数组然后检查这两个性质。如果发现上下不对称问题基本出在d的表达式上。你可以打印出每一行的row, d, left, right对照表格数据排查。4.3 蓝桥杯 OJ 的提交细节如果你是在蓝桥杯系统里做题还有一些细节要注意Java 提交时类名必须是Main不要写public class Main以外的类名。C 提交时确保使用using namespace std;或者写全std::cin、std::cout。Python 提交时不需要额外的装饰器直接读输入即可。输入可能包含多组数据。有的题目说“输入一个正整数 n”那就只读一个如果题目说“多组输入”你就需要写while (cin n)或者while (sc.hasNext())。具体以题目要求为准。今天讨论的核心逻辑不依赖这个拿一组数据也能跑通。还有一点蓝桥杯的评测环境里输出的空格会被原样比较。所以千万不要用println输出一整行后统一trim再打印那样会把行首空格也删掉图形直接歪了。正确的做法是在构建每一行时就精确控制字符。5. 进阶思路从六芒星到复杂图形5.1 实心六芒星的扩展写法如果你把题目要求改成“实心”而不是轮廓只需要把内层循环的条件改一下for (int col 0; col right; col) { if (col left col right) { sb.append(*); } else { sb.append( ); } }这样每一行从左边界到右边界全部填充*最终会形成一个实心的菱形/沙漏形。很多题目会在这个基础上继续变比如要求分成上下两个三角形中间留一条空格带或者要求用数字来打印。实心写法和轮廓写法的区别本质上就是“判断单个点”还是“判断区间”。轮廓写法判断两个边界点实心写法判断边界之间的连续区间。解题的坐标系和偏移量完全不变。5.2 碰到真正的“几何六芒星”怎么办有时候题目里的图案不是这种沙漏形而是几何学意义上的六角星也就是两个等边三角形中心重叠、旋转 180 度后的效果。这种图形用上面的行列偏移公式也能做但公式会复杂很多需要区分 12 条边。我的建议是做题时不要死记公式。你可以在稿纸上把外轮廓的关键点坐标标出来然后用“逐点判断”的方式枚举画布上的每一个点判断它是否落在六芒星轮廓上。这个方法虽然时间复杂度高一点但在n不大的情况下完全够用而且逻辑不容易出错。蓝桥杯这类题目通常n不会超过 20所以不要担心性能。追求最优解之前先保证自己能稳定拿到分数。5.3 相似的打印图形题都可以用同一套路除了六芒星蓝桥杯还考过“打印大 X”“打印十字图”“打印菱形”等题目。它们都有一个共同点图形关于中心行和中心列对称。所以解题步骤可以通用算总行数和总列数。找到中心行、中心列。对每一行用“偏移量”描述星号位置的范围。写两层循环输出。我曾经遇到一个打印“十字图”的填空题当时就是靠这个套路反推代码填空的。所以这篇文章讲的不只是六芒星一道题而是一类“对称图形打印题”的通用方法论。我自己在实际操作中还有一个小习惯先用纸笔画一个n4的网格在每一个非空格位置写上它的行号和列号。这个过程看起来很基础但能帮你发现很多隐性问题。尤其是当图形不是单纯“距离中心越远越宽”时坐标标号远比空想可靠。如果你能把六芒星的规律吃透再去做其他打印图形题会发现世界一下子清晰了很多。
返回列表