法1:

我的思路及其简单

实现及其复杂

运行有5ms

主要思路是首先将模板矩阵,读入一个5*5的Temp矩阵中

计算出将要打印内容的矩阵大小

随后在足够大的ForPrint矩阵中,逐个位置遍历,确定其符号

是空格还是其他

确定符号的方法是:

考虑最外层,可以看做是次外层,按照原来模板的状态逐个对应的

凡是原来模板有空格的,当前次外层模块全部为空格

对每个点都遍历所有层次,一旦发现位于某一层的空格次外层模块时

则设置空格标记,并跳出层次遍历的循环

只有当所有层都不是空格时,才按照原给定模板对其赋值

//通过公式计算,得到新的矩阵
#include <stdio.h>
#include <math.h>
#define MAXSIZE 150

//将给定模板复制
void Repeat(char (*Temp)[5], int Size,
            char (*ForPrint)[MAXSIZE],
            int RepeatTime)
{
    int PrintSize = pow(Size, RepeatTime);
    int SpaceFlag = 0; //用于标记是否在复制过程中有一次是空格
    //遍历ForPrint数组,写入对应值
    for (int i = 0; i < PrintSize; i++)
        for (int j = 0; j < PrintSize; j++)
        {
            SpaceFlag = 0;
            for (int k = 1; k <= RepeatTime; k++)
            {
                int useful = pow(Size, k);
                int temp_i = floor(((i % useful)) / (pow(Size, k - 1)));
                int temp_j = floor((j % useful) / (pow(Size, k - 1)));
                if (Temp[temp_i][temp_j] == ' ')
                {
                    SpaceFlag = 1;
                    break;
                }
            }
            if (SpaceFlag)
                ForPrint[i][j] = ' ';
            else
                ForPrint[i][j] = Temp[i % Size][j % Size];
        }
}

//具体打印出已经保存好的值
void PrintForPrint(char (*ForPrint)[MAXSIZE], int Size, int RepeatTime)
{
    int PrintSize = pow(Size, RepeatTime);
    //将各行各列打印出来
    for (int i = 0; i < PrintSize; i++)
    {
        for (int j = 0; j < PrintSize; j++)
            printf("%c", ForPrint[i][j]);
        printf("\n");
    }
}

int main()
{
    int Size = 0;
    int RepeatTime = 0;
    char Temp[5][5] = {0};
    char ForPrint[MAXSIZE][MAXSIZE] = {0};
    char c;
    int flagN = 0;         //用于保存第几个数字
    int flagL = 0;         //用于保存已经存入了多少行
    int flagFirstLine = 0; //用于剔除第一个行号
    int flagLastLine = 0;  //用于剔除最后一个行号
    int LineNum = 0;

    while (scanf("%c", &c) != EOF)
    {
        if (flagN == 1 && flagL != Size)
        {
            if (c == '\n')
            {
                if (flagLastLine == 1)
                {
                    flagLastLine = 0;
                    flagN = 0;
                    continue;
                }
                else if (flagFirstLine == 1)
                {
                    flagFirstLine = 0;
                    LineNum = 0;
                    continue;
                }
                else
                {
                    flagL++, LineNum = 0;
                    continue;
                }
            }
            Temp[flagL][LineNum++] = c;
        }
        if (flagLastLine == 0 && flagN == 0 && flagFirstLine == 0)
        {
            if (c == '0')
                break;
            flagN++;
            flagFirstLine = 1;
            Size = c - '0';
        }
        if (flagL == Size)
        {
            flagL = 0;
            flagLastLine = 1;
            RepeatTime = c - '0';
            Repeat(Temp, Size, ForPrint,
                   RepeatTime);
            PrintForPrint(ForPrint, Size, RepeatTime);
        }
    }
}

法2:

借鉴别人的做法

他用的方法与我不同

使用了递归的方法

递归一层的参数分别是q,x,y

其中q是递归层级

x,y分别是起始点的坐标

首先,初始模板存入t矩阵中

p矩阵为待画矩阵

两者均为全局变量

递归出口为层数为1时,即将从对应的x,y位开始的模块填充进去

在一般情况下,则遍历当前层次的次层次模块

若该次层次模块不为空格时,则递归遍历该次层次模块

#include <stdio.h>
#include <math.h>

int N, Q;
char t[6][6];
char p[3000][3001];

void draw(int q, int x, int y)
{
    int eSize = (int)pow(N, q - 1);

    int i, j;
    if (q == 1)
    {
        for (i = 0; i < N; i++)
        {
            for (j = 0; j < N; j++)
            {
                p[x + i][y + j] = t[i][j];
            }
        }
    }
    else
    {
        for (i = 0; i < N; i++)
        {
            for (j = 0; j < N; j++)
            {
                if (t[i][j] != ' ')
                {
                    draw(q - 1, x + eSize * i, y + eSize * j);
                }
            }
        }
    }
}

int main()
{
    while (scanf("%d", &N) != EOF)
    {
        if (N == 0 || N > 5)
        {
            break;
        }
        //去掉多余的换行符
        getchar();
        //输入模板
        int i, j;
        for (i = 0; i < N; i++)
        {
            gets(t[i]);
        }
        scanf("%d", &Q);
        int size = (int)pow(N, Q);
        //格式化图画
        for (i = 0; i < size; i++)
        {
            for (j = 0; j < size; j++)
            {
                p[i][j] = ' ';
            }
            p[i][size] = '\0';
        }
        draw(Q, 0, 0);
        for (i = 0; i < size; i++)
        {
            puts(p[i]);
        }
    }
    return 0;
}

接下来学习他的字符串操作

使用c=getchar();可以一次读取一个字符,多余的键盘上的字符全部存入键盘buff中

使用gets(char*);可以读入一行数据,遇到换行符则退出;但是容易被蠕虫攻击,故不能用gets().

法3:

//每次将不为空格的字符替换为模板即可
#include <iostream>
#include <vector>
#include <string>

using namespace std;

void duplicate(vector<string> &s, vector<string> &temp)
{
    string SpaceString(s.size() * temp.size(), ' ');
    vector<string> res(s.size() * temp.size(), SpaceString);
    //新的res是用来保存下一层待打印数据的
    // s中是已有层待打印数据

    for (int i = 0; i < s.size(); i++)
    {
        for (int j = 0; j < s[i].size(); j++)
        {                       //这两个for循环用于遍历之前的s[]数组
            if (s[i][j] != ' ') //若不是空格,才将输入模板,复制到下一层待打印数据res中去
            {
                for (int k = 0; k < temp.size(); k++)
                { //这个循环用于将每一行的模板数字,复制到res中
                    //当前行在res中定位在i*temp.size()+k这一行
                    res[i * temp.size() + k].replace(
                        res[i * temp.size() + k].begin() + j * temp.size(),
                        res[i * temp.size() + k].begin() + j * temp.size() + temp.size(),
                        temp[k]);
                } // begin()返回容器指针
                // replace(*type,int count,*templ)或者replace(*begin,*end,*templ)
                //此for循环结束后,原模板的逐行拷贝即完成
            }
        }
    }
    s = res;
}
int main()
{
    int N, Q;
    while (cin >> N)
    {
        if (N == 0)
            return 0;
        vector<string> temp(N);
        getline(cin, temp[0]); //用于取出第一行数字之后的'\n',并在后面进行覆盖
                               //取到\n时,getline自动结束本行,其中不存入\n
                               //故此时temp[0]中什么也没有
        cout << temp[0];
        for (int i = 0; i < N; getline(cin, temp[i++]))
            ;
        vector<string> res(temp); //直接复制过来了temp动态数组
                                  //此处是第一层
        cin >> Q;
        for (int i = 1; i < Q; i++)
        {
            duplicate(res, temp);
        } //根据层数逐级增大即可
        for (int i = 0; i < res.size(); i++)
        {
            cout << res[i] << endl;
        }
    }
}