洛谷P1498南蛮图腾&&nkoj分形2

题目背景

自从到了南蛮之地,孔明不仅把孟获收拾的服服帖帖,而且还发现了不少少数民族的智慧,他发现少数民族的图腾往往有着一种分形的效果,在得到了酋长的传授后,孔明掌握了不少绘图技术,但唯独不会画他们的图腾,于是他找上了你的爷爷的爷爷的爷爷的爷爷……帮忙,作为一个好孙子的孙子的孙子的孙子……你能做到吗?

题目描述

给定一个正整数 n n n,参考输出样例,输出图形。

输入格式

每个数据输入一个正整数 n n n,表示图腾的大小(此大小非彼大小)。

输出格式

这个大小的图腾。

样例

样例输入1

1

样例输出1

 /\
/__\

样例输入2

2

样例输出2

   /\
  /__\
 /\  /\
/__\/__\

样例输入3

3

样例输出3

       /\
      /__\
     /\  /\
    /__\/__\
   /\      /\
  /__\    /__\
 /\  /\  /\  /\
/__\/__\/__\/__\

说明/提示

数据保证, 1 ≤ n ≤ 10 1 \le n \le 10 1n10

思路

首先,我们观察样例输出的长,宽。
n = 1 n = 1 n=1 时,长 4 4 4格,宽 2 2 2格。
n = 2 n = 2 n=2 时,长 8 8 8格,宽 4 4 4格。
n = 3 n = 3 n=3 时,长 16 16 16格,宽 8 8 8格。
通过上述的数据,我们可以发现,长 2 n + 1 2 ^ {n + 1} 2n+1格,宽 2 n 2 ^ n 2n格。
因为 1 ≤ n ≤ 10 1 \le n \le 10 1n10,所以我们至少要开一个 2048 × 1024 2048 \times1024 2048×1024 的数组存储答案。
其次,我们来观察图形。
图形包含许多的三角形。
我们发现,最小的三角形边长为 2 2 2,每一个三角形的变成是比其小的三角形的边长 × 2 \times 2 ×2,且每一个三角形都包含 3 3 3 个比其小的三角形,位置在最上方,左下方和右下方。
由此,我们可以考虑递归。
从最大的三角形(边长为 2 n 2 ^ n 2n)开始递归,每次画出三角形,并找出各边的中点向下一层递归。如果边长等于 1 1 1,返回。
具体细节详见代码。

注意事项

  1. 答案数组最初要初始化为‘ ’(空格),否则系统默认为 ASCLL码 为 0 0 0 的字符。虽然也能输出空格,但会被系统判错(不可见字符);
  2. 注意你的数组下标是从 0 0 0 开始的还是 1 1 1 开始的;
  3. 字符’‘需要转义(即’\');
  4. 数组不要开成 1024 × 1024 1024 \times 1024 1024×1024

代码

#include<bits/stdc++.h>
using namespace std;
int n;
char mp[4000][4000];
void dfs(int x, int y, int p){
    int tx1, tx2;//左边中点坐标
    int ty1, ty2;//右边中点坐标
    if(p == 1){//边长为1
        return;
    }
    int u = p / 2;//下一层边长
    //画左边的边
    int px = x, py = y;
    for(int i = 1; i <= p; ++ i){
        mp[px][py] = '/';
        px ++;
        py --;
        if(i == u){
            tx1 = px;
            ty1 = py;
        }
    }
    int t = py + 1;
    //画右边的边
    px = x, py = y + 1;
    for(int i = 1; i <= p; ++ i){
        mp[px][py] = '\';//转义
        px ++;
        py ++;
        if(i == u){
            tx2 = px;
            ty2 = py - 1;
        }
    }
    -- px;
    -- py;
    //下面的边
    for(int i = t + 1; i < py; ++ i){
        mp[px][i] = '_';
    }
    //下一层
    dfs(x, y, u);
    dfs(tx1, ty1, u);
    dfs(tx2, ty2, u);
}
int main(){
    scanf("%d", &n);
    //计算最大三角形的边长(同时也是宽和长的一半)
    //注意,pow函数可能会因精度误差而导致计算错误
    int s = 1;
    for(int i = 1; i <= n; ++ i){
        s *= 2;
    }
    //初始化,可以用memset(mp, ' ', sizeof(mp))
    for(int i = 1; i <= s; ++ i){
        int t = s * 2;
        for(int j = 1; j <= t; ++ j){
            mp[i][j] = ' ';
        }
    }
    dfs(1, s, s);
    for(int i = 1; i <= s; ++ i){
        int t = s * 2;
        for(int j = 1; j <= t; ++ j){
            putchar(mp[i][j])}
        putchar('\n');
    }
    return 0;
}
  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值