算法竞赛进阶指南0x08练习4:Fractal

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

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

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

一级盒子分形:

   X

二级盒子分形:

   X X
    X
   X X

如果用 B(n−1) 代表第n−1 级盒子分形,那么第 n 级盒子分形即为:

  B(n - 1)        B(n - 1)

          B(n - 1)

  B(n - 1)        B(n - 1)

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

输入格式

输入包含几个测试用例。

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

输入的最后一行为 −1,代表输入结束。

输出格式

对于每个测试用例,使用 X 符号输出对应等级的盒子分形。

请注意 X 是一个大写字母。

每个测试用例后输出一个独立一行的短划线。

输入样例:

1
2
3
4
-1

输出样例

X
-
X X
 X
X X
-
X X   X X
 X     X
X X   X X
   X X
    X
   X X
X X   X X
 X     X
X X   X X
-
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
   X X               X X
    X                 X
   X X               X X
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
         X X   X X
          X     X
         X X   X X
            X X
             X
            X X
         X X   X X
          X     X
         X X   X X
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
   X X               X X
    X                 X
   X X               X X
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
-

思路:

找规律:
递归找规律,我们可以发现对于每个盒子都是正方形,边长都一样;

对于第n级的盒子分型,其边长为3^(n-1),例如2级盒子边长为3,3级盒子边长为9;

对于第n级盒子,总是由n-1级盒子复制到其他四个地方的;

n-1级盒子在左上角,n级盒子需要其复制到右上角,中间,左下角,右下角

                                                        (画的有点丑,见谅)

解法:                                                                                                


用一个二维数组表示整个7级盒子,如果某个位置该放'X',就将其值置为1,否则为0;

先进行一次性预处理,求出7级盒子的样子,再根据输入的数值,输出对应大小的数组;

我们可以用len_n表示第n级盒子的边长,len_n_1表示第n-1级盒子的边长;

则我们可以发现,n级盒子右上角距离n-1级盒子的距离为2倍len_n_1,

等于将n-1级盒子向右平移2倍len_n_1的距离;

中间的部分等于n-1级盒子向下平移len_n_1,再向右平移len_n_1的距离;

左下角的部分等于n-1级盒子向下平移2倍len_n_1的距离;

右下角的部分等于n-1级盒子向右平移2倍len_n_1,向下平移2倍len_n_1的距离;

由此,递归的关系式就非常简单了,我们可以像一般的深搜一样,用两个一维数组表示行和列的变化(单位是len_n_1); 

然后根据变化前的状态确定变化后的状态;(由于是复制过来的,所以变化前后状态一样); 

    最后根据输入的数字,输出对应边长大小的矩阵;

#include<iostream>
using namespace std;
const int N=1e3;
int B[N][N];
void dfs(int n){
    if(n==1) {//第n级盒子只有一个'X';
        B[0][0]=1;
        return;
    }
    dfs(n-1);
    int len_n_1=1;//表示n-1级盒子边长;
    for(int i=1;i<=n-2;++i)
        len_n_1*=3;
    int dx[4]={0,1,2,2,},dy[5]={2,1,0,2};//表示行和列的变化,单位为len_n_1;
    for(int i=0;i<4;++i)
        for(int j=0;j<len_n_1;++j)
            for(int k=0;k<len_n_1;++k)
                B[dx[i]*len_n_1+j][dy[i]*len_n_1+k]=B[j][k];//将变化前的值复制给变化后的值;
    return;
}
int main()
{
    dfs(7);
    int n;
    while(cin>>n&&n!=-1){
        int len_n=1;//len_n表示n级盒子边长;
        for(int i=1;i<=n-1;++i) 
            len_n*=3;//边长=3^(n-1);
        for(int i=0;i<len_n;++i){//根据输入的数值大小,输出对应边长大小的数组;
            for(int j=0;j<len_n;++j)
                if(B[i][j]==1) cout<<'X';//某一位值为1表示该输出'X',否则输出空格;
                else cout<<' ';
            cout<<endl;
        }
        cout<<'-'<<endl;
    }
}

题目提交地址:提交地址

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值