南蛮图腾

GitHub跳转原题关系图返回列表

从最小三角形开始,每次把旧图放在上方居中和下方左右两份,迭代生成分形图案。

OJ: luogu

题目 ID: P1498

难度:入门

标签:递归分形字符串python

日期: 2026-07-15 22:30

题意

给定 n,输出对应大小的三角分形图腾。

思路

n=1 的基础图形开始:

text
 /\
/__\

每放大一层:

  • 上半部分:旧图整体居中;
  • 下半部分:左右各放一份旧图。

这样迭代到第 n 层即可。

也可以用递归(DFS)的视角看同一件事:n 层图腾由 1 个上方2 个下方n-1 层图腾组成,而最小单元就是上面那个两行四列的三角形。递归函数 dfs(x, y, level)(x,y) 为底部中心画 level 层图腾,子图腾相对中心偏移 2^(level-1)

Python 知识

  • 字符串可以用 line + line 拼接成左右两份。
  • " " * height 用来补居中空格。
  • 输出时 rstrip() 去掉右侧多余空格,但保留左侧缩进。

参考笔记:

  • /home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md

代码

python
n = int(input())

picture = [
    " /\\ ",
    "/__\\",
]

for _ in range(2, n + 1):
    height = len(picture)
    top = [" " * height + line + " " * height for line in picture]
    bottom = [line + line for line in picture]
    picture = top + bottom

for line in picture:
    print(line.rstrip())
cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-27 00:00
 * update_at: 2026-07-27 00:00
 */
#include <bits/stdc++.h>
using namespace std;

int n;
string pic[2500];

int main() {
    cin >> n;
    pic[0] = " /\\ ";
    pic[1] = "/__\\";
    int h = 2;
    for (int k = 2; k <= n; k++) {
        string tmp[2500];
        for (int i = 0; i < h; i++) tmp[i] = pic[i];
        for (int i = 0; i < h; i++) pic[i] = string(h, ' ') + tmp[i] + string(h, ' ');
        for (int i = 0; i < h; i++) pic[i + h] = tmp[i] + tmp[i];
        h *= 2;
    }
    for (int i = 0; i < h; i++) {
        int pos = pic[i].find_last_not_of(' ');
        cout << pic[i].substr(0, pos + 1) << endl;
    }
    return 0;
}

代码 (DFS)

用递归分治从底部中心开始画图,无需维护行宽。

cpp
#include <bits/stdc++.h>
using namespace std;

int n;
char pic[1050][2050];

// 以 (x,y) 为"底部中心"画 level 层图腾
void dfs(int x, int y, int level) {
    if (level == 1) {                    // 最小单元:2行4列
        pic[x-1][y-1] = '/';
        pic[x-1][y]   = '\\';
        pic[x][y-2]   = '/';
        pic[x][y-1]   = '_';
        pic[x][y]     = '_';
        pic[x][y+1]   = '\\';
        return;
    }
    int half = 1 << (level - 1);         // 子图腾高/半宽 = 2^(level-1)
    dfs(x - half, y, level - 1);         // 上方
    dfs(x, y - half, level - 1);         // 左下方
    dfs(x, y + half, level - 1);         // 右下方
}

int main() {
    cin >> n;
    memset(pic, ' ', sizeof(pic));
    int h = 1 << n;                      // 总高 2^n
    dfs(h - 1, h, n);                    // 底部中心 (2^n-1, 2^n)
    for (int i = 0; i < h; i++) {
        int end = (1 << (n+1)) - 1;
        while (pic[i][end] == ' ') end--;
        for (int j = 0; j <= end; j++) cout << pic[i][j];
        cout << endl;
    }
    return 0;
}

复杂度

最终图形高度为 2n2^n,宽度为 2n+12^{n+1},时间和空间复杂度都与输出规模同阶。

总结

字符画题最重要的是先找到“上一层如何拼成下一层”。这里就是上方居中、下方复制两份。