算法设计与分析 SCAU18931 分形

18931 分形

时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0

在这里插入图片描述

题型: 编程题 语言: G++;GCC;VC;JAVA

Description

分形,具有以非整数维形式充填空间的形态特征。

通常被定义为“一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。

现在,定义“盒子分形”如下:

一级盒子分形:

X
二级盒子分形:

X X
X
X X

如果用B(n - 1)代表第n-1级盒子分形,那么第n级盒子分形即为:
在这里插入图片描述

你的任务是绘制一个n级的盒子分形。


输入格式

输入一个不大于6的正整数n,代表要输出的盒子分形的等级。


输出格式

使用“X”符号输出对应等级的盒子分形。


输入样例

4


输出样例

在这里插入图片描述


解题思路

递归

找规律

此题可用递归解决,递归的思想可查看下图:

第一次递归
此时 n = 4
在这里插入图片描述
第二次递归
此时 n = 3
在这里插入图片描述
第三次递归
此时 n = 2
在这里插入图片描述
第四次递归
此时 n = 1,结束递归

因此我们可以不断地往左上角、右上角、中心、左下角、右下角进行递归(即五次)



那我们如何在第一、第二次递归等等,确定我要找的位置在哪里呢?
我们可以用草稿纸帮助我们计算

  • 第一次递归,右上角距离左上角为18个单位
  • 第二次递归,右上角距离左上角为6个单位
  • 第三次递归,右上角距离左上角为2个单位

这些数字有什么特点呢

  • 18 = 3 ^ 3 - 3 ^ 2(n = 4)
  • 6 = 3 ^ 2 - 3 ^ 1(n = 3)
  • 2 = 3 ^ 1 - 3 ^ 0(n = 2)

即为 3 ^ (n - 1) - 3 ^ (n - 2)

因此相对于左上角为基准点来说,右上角、左下角、右下角的位置可以通过该方法进行确定

  • 而中心的位置我们也可以看出来距离为 3 ^ 2

因此该题距离已知道如何确定,并以此来进行后续递归即可


递归终止条件

条件为 n = 1 时,此时将当前的 x 和 y 的位置置为题目要求的字符 ‘X’ 即可

算法思路
  1. 由于此题的 n 不大于6,所以宽高不大于 3 的 6-1=5 即5次方,即243,因此初始化一个宽高为 250 的数组 a 即可
  2. 将数组 a 初始化为空格,比如 n = 4 时,3 ^ 3 = 27,因此将数组 a 宽27高27的位置全初始化为空格
  3. 进行递归,每次递归都往左上角、右上角、中心、左下角、右下角进行递归
  4. 输出数组 a



更多注释可查看下方的完整代码中,有助于理解

代码如下
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <utility>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
/*
4
*/
using namespace std;
const int N = 1050;
const int inf = 1e9+7;
const int mod = 1e9+7;
const double pi = acos(-1.0);
const double eps = 1e-9;
typedef long long ll;

int n;
char a[250][250]; // 由于此题的 n 不大于6,所以宽高不大于 3 的 6-1=5 即5次方,即243

// cur 为传了几次,i 为传到序号为几的人手上
void dfs(int cur, int x, int y) {
    // 最后一个图形就不用递归咯
    if(cur == 1) {
        a[x][y] = 'X';
        return;
    }

    // 当为第 n 次时,总图形为 3 的 n - 1 次方的宽高,且右上角位置为 3 的 n - 1 次方减去 3 的 n - 2 次方,其他位置也是这个规律
    int len = pow(3, cur - 1);
    int sub = pow(3, cur - 2);

    dfs(cur - 1, x, y); // 左上角
    dfs(cur - 1, x, y + len - sub); // 右上角
    dfs(cur - 1, x + sub, y + sub); // 正中心
    dfs(cur - 1, x + len - sub, y); // 左下角
    dfs(cur - 1, x + len - sub, y + len - sub); // 右下角
}


int main()
{
    // 每个图形宽3高3,因此为 3 的 n - 1 次方的宽高总共
    cin >> n;

    int len = pow(3, n - 1);

    for(int i = 0; i < len; i++) {
        for(int j = 0; j < len; j++) {
            a[i][j] = ' '; // 把该盒子都变为空格先
        }
    }

    dfs(n, 0, 0);

    for(int i = 0; i < len; i++) {
        for(int j = 0; j < len; j++) {
            cout << a[i][j];
        }
        cout << endl;
    }

    return 0;
}


最后

对我感兴趣的小伙伴可查看以下链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值