首页 > 试题广场 >

Repeater

[编程题]Repeater
  • 热度指数:8999 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
Harmony is indispensible in our daily life and no one can live without it----may be Facer is the only exception. One day it is rumored that repeat painting will create harmony and then hundreds of people started their endless drawing. Their paintings were based on a small template and a simple method of duplicating. Though Facer can easily imagine the style of the whole picture, but he cannot find the essential harmony. Now you need to help Facer by showing the picture on computer. You will be given a template containing only one kind of character and spaces, and the template shows how the endless picture is created----use the characters as basic elements and put them in the right position to form a bigger template, and then repeat and repeat doing that. Here is an example. # #  #      <-template # # So the Level 1 picture will be # #  # # # Level 2 picture will be # #     # #  #         # # #     # #      # #         #         # #   # #    # #  #        # # #    # #

输入描述:
The input contains multiple test cases.
The first line of each case is an integer N, representing the size of the template is N*N (N could only be 3, 4 or 5).
Next N lines describe the template.
The following line contains an integer Q, which is the Scale Level of the picture.
Input is ended with a case of N=0.
It is guaranteed that the size of one picture will not exceed 3000*3000.


输出描述:
For each test case, just print the Level Q picture by using the given template.
示例1

输入

3
# #
 # 
# #
1
3
# #
 # 
# #
3
4
 OO 
O  O
O  O
 OO 
2
0

输出

# #
 # 
# #
# #   # #         # #   # #
 #     #           #     # 
# #   # #         # #   # #
   # #               # #   
    #                 #    
   # #               # #   
# #   # #         # #   # #
 #     #           #     # 
# #   # #         # #   # #
         # #   # #         
          #     #          
         # #   # #         
            # #            
             #             
            # #            
         # #   # #         
          #     #          
         # #   # #         
# #   # #         # #   # #
 #     #           #     # 
# #   # #         # #   # #
   # #               # #   
    #                 #    
   # #               # #   
# #   # #         # #   # #
 #     #           #     # 
# #   # #         # #   # #
     OO  OO     
    O  OO  O    
    O  OO  O    
     OO  OO     
 OO          OO 
O  O        O  O
O  O        O  O
 OO          OO 
 OO          OO 
O  O        O  O
O  O        O  O
 OO          OO 
     OO  OO     
    O  OO  O    
    O  OO  O    
     OO  OO     
#include<iostream>
(720)#include<cstdio>
#include<string>

using namespace std;

int n;    //原始模板大小
int len;   //现在模板大小
char model[6][6];    //原始模板
char m1[3000][3000];   //保存现在的模板
char m2[3000][3000];   //保存新产生的模板

void change(int x, int y, int flag)   //x y 为现在的起点  1的时候用现有模板填充 0的时候用空格
{
    for (int i = 0; i < len; i++)
        for (int j = 0; j < len; j++)
        {
            if (flag)
                m2[i + x][j + y] = m1[i][j];
            else
                m2[i + x][j + y] = ' ';
        }
}

void deal()     //根据原始模板决定是否替换
{
    for(int i=0;i<n;i++)
        for (int j = 0; j < n; j++)
        {
            if (model[i][j] != ' ')
                change(i*len, j*len, 1);  //用现有模板替换
            else
                change(i*len, j*len, 0);
        }
}

void getnew()   //更新现在的模板
{
    for (int i = 0; i < len * n; i++)
        for (int j = 0; j < len * n; j++)
            m1[i][j] = m2[i][j];
}

int main()
{
    while (cin >> n)
    {
        getchar();  //吃掉回车
        if (n == 0) break;
        for (int i = 0; i < n; i++)
        {
            string temp;
            getline(cin,temp);
            for (int j = 0; j < temp.size(); j++)
                model[i][j] = temp[j];
        }
        int num;
        cin >> num;
        //接收输入结束

        //产生现有的模板
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                m1[i][j] = model[i][j];

        //开始用现有模板替代原有的元素
        for (int k = 1; k < num; k++)
        {
            len = pow(n,k);   //现在模板的大小
            deal();
            getnew();
        }

        //输出
        len = pow(n,num);
        for (int i = 0; i < len; i++)
        {
            for (int j = 0; j < len; j++)
                if (num == 1)
                    cout << m1[i][j];
                else
                    cout << m2[i][j];
            cout << endl;
        }
    }
    return 0;
}

发表于 2020-04-22 14:11:49 回复(3)
1、一倍一倍放大
2、按照起初模板一行一行变大
3、一直对起初模板进行变大,空格变长为模板长度的倍数,符号变为上一倍数对应的行
Python的字符串替换函数挺好用的
try:
    while True:
        num = int(input())
        if num == 0:break
        result = []                     #输出结果
        template = []                   #起初模板(不变)
        for i in range(num):
            template.append(input())
            result.append(template[i])
        sign = result[0].split()[0][0]  #得到符号
        zoomsNum = int(input())
        for i in range(1,zoomsNum):     #i为放大的倍数
            replaceNum = num**i
            example = []                #保存着前一个倍数的模板
            blanks = " "*replaceNum     #当前倍数比较起初模板空格被放大的倍数
            for j in range(num):        #j为起初模板对于的行
                for k in range(replaceNum):       #k是对应起初模板的一行中被放大倍数后的行数
                    if j == 0:
                        example.append(result[k])    #保存着前一个倍数的模板  
                        result[k] = template[j].replace(" ",blanks)         #在起初第一行模板不需要增加行数,所以只需要放大空格和符号sign就好
                    else:
                        result.append(template[j].replace(' ',blanks))
                    signLines = example[k]           #把每一个符号位替换成上一个倍数对应的行
                    result[k+j*replaceNum] = result[k+j*replaceNum].replace(sign,signLines)
        for i in result:
            print(i)
except Exception:
    pass
编辑于 2018-10-04 09:54:39 回复(1)
牛客网真心蠢,重新绑定手机把我账号信息清除了,我服。。。。。
#include <bits/stdc++.h>
using namespace std;
char base[5][5];
char mm[3000][3000];
int N,Q;
char w;//用来记录所用的特殊符号
struct point{
    int x,y;
    point(int a,int b):x(a),y(b){}
};
vector<point>mybase;//将坐标中心放到中心,而不是从左上角开始,存到这里,只记录符号w
struct point2{
    double x,y;
    point2(double a,double b):x(a),y(b){}
};
vector<point2>mybase2;//这个主要用于将奇数偶数计算中心的方法合并,只能用小数来算,
//不然形状就不是从中心发展(偶数情况)

void draw(int x,int y,int level){
    if(level==1){//level==1,直接将对应位置为w
        for(int i=0;i<mybase.size();i++)
        {
            mm[x+mybase[i].x][y+mybase[i].y]=w;
        }
    }
    else {
        //如果不是level1 ,就递归往下画
        for(int i=0;i<mybase.size();i++){
            draw(int(mybase2[i].x*pow(N,level-1)+x),int(mybase2[i].y*pow(N,level-1)+y),level-1);
        }
    }
}
void show(int x,int y,int level){
    //画的是N^level*N^level 的矩阵,找到其左上角和右下角的坐标
    int xlow,ylow,xhigh,yhigh;
    if(N%2==1){
        // n为奇数
        xlow=x-pow(N,level)/2+1;
        ylow=y-pow(N,level)/2+1;
        xhigh=x+pow(N,level)/2;
        yhigh=y+pow(N,level)/2;

    }
    else{
        xlow=x-pow(N,level)/2;
        ylow=y-pow(N,level)/2;
        xhigh=x+pow(N,level)/2-1;
        yhigh=y+pow(N,level)/2-1;
    }
    for(int i=xlow;i<=xhigh;i++){
        for(int j=ylow;j<=yhigh;j++){
            cout<<mm[i][j];
        }
        cout<<endl;
    }
}
int main(){
    freopen("in.txt","r",stdin);
    while(scanf("%d",&N)!=EOF&&N){
        memset(base,' ',sizeof(base));
        memset(mm,' ',sizeof(mm));
        mybase.clear();
        mybase2.clear();
        int cx=N/2;
        int cy=N/2;
        double dcx=(N-1)/2.0;
        double dcy=dcx;
        getchar();//吸收换行符
        for(int i=0;i<N;i++){
            gets(base[i]);
            for(int j=0;j<N;j++){
                if(base[i][j]!=' '){
                    mybase.push_back(point(i-cx,j-cy));
                    mybase2.push_back(point2(i-dcx,j-dcy));
                    w=base[i][j];
                }
            }
        }
        cin>>Q;
        draw(1500,1500,Q);
        show(1500,1500,Q);
    }
    return 0;
}

发表于 2018-06-09 17:35:08 回复(0)
#include<bits/stdc++.h>
using namespace std;
void printchar ** arr,int n){
    for (int i = 1i <=n; i++)
    {
        for (int j = 1j <n; j++)
        {
            printf("%c",arr[i][j]);
        }
        printf("%c\n",arr[i][n]);
    }
}
int main(){
    int N;
    scanf("%d",&N);
    char original[6][6];
    while(N!=0){
        getchar();
        char **temp=new char*[N+1];
        for (int i = 0i <N+1i++)
        {
            temp[i]=new char[N+1];
        }
        for (int i = 1i <= Ni++)
        {
            for (int j = 1j <=Nj++)
            {
                scanf("%c",&temp[i][j]);
                original[i][j]=temp[i][j];
            }
            getchar();
        }
        int level;
        scanf("%d",&level);
        int cursize;
        char **arr;
        int presize=1;
        for (int i = 1i<= leveli++)
        {
            cursize=(int)(pow(N,i)+0.5);
            arr=new char*[cursize+1];
            for (int i = 0i < cursize+1i++)
            {
                arr[i]=new char[cursize+1];
            }
            for(int j=1;j<=cursize;j++){
                for(int m=1;m<=cursize;m++){
                    if(presize==1){
                        arr[j][m]=temp[j][m];                       
                    }else{
                        int x=(int)ceil((double)j/N);
                        int y=(int)ceil((double)m/N);
                        // 确定缩放点原位置是否是character
                        if(temp[x][y]!=' '){
                            int x=j%N!=0?j%N:N;
                            int y=m%N!=0?m%N:N;
                            arr[j][m]=original[x][y];
                        }else{
                            arr[j][m]=' ';
                        }
                    }
                }
            }
            for(int i=0;i<presize+1;i++){
                delete[] temp[i];
            }
            delete[] temp;
            presize=cursize;
            temp=arr;
        }
        print(arr,cursize);
        scanf("%d",&N);
    }
    return 0;
}
发表于 2021-07-16 22:49:31 回复(0)
分析画图问题,可以发现这是一个递归,对输入图形的每一个非空字符都进行套娃,用输入图形来替换非空字符的位置,并且根据q的值套多次。可以写一个子程序来递归的创建二维字符数组,最后把这个字符数组输出
#include<iostream>
(720)#include<math.h>
using namespace std;
char** fillOutput(char** temp, int n, int size, int q);
int main()
{
    int n, q;
    while (cin >> n) {
        if (n == 0) break;
        cin.ignore();
        char** temp = new char* [n];    //创建二维数组temp存储template
        for (int i = 0; i < n; i++) {
            temp[i] = new char[n];
        }
        for (int i = 0; i < n; i++) {            //逐行读取template
            cin.getline(temp[i], n + (int)1);
        }
        cin >> q;
        int size = (int)pow(n, q);
        char** output = new char* [size];
        for (int i = 0; i < n; i++) {
            output[i] = new char[size];
        }
        output = fillOutput(temp, n, size, q);
 
        for (int i = 0; i < size; i++) {
            cout << output[i] << endl;
        }
    }
 
    return 0;
}
char** fillOutput(char** temp, int n, int size, int q) {
    if (q == 1) return temp;
    int lowSize = size / n;
    char** subMatrix = new char* [size];
    for (int i = 0; i < size; i++) {
        subMatrix[i] = new char[size];
    }
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            subMatrix[i][j] = ' ';
        }
    }
    for (int i = 0; i < n * lowSize; i += lowSize) {
        for (int j = 0; j < n * lowSize; j += lowSize) {
            if (temp[i / lowSize][j / lowSize] == ' ') continue;          
            char** subsub = fillOutput( temp, n, lowSize, q - 1);
            for (int m = i; m < i + lowSize; m++) {
                for (int n = j; n < j + lowSize; n++) {
                    subMatrix[m][n] = subsub[m - i][n - j];
                }
            }
        }
    }
    return subMatrix;
}




发表于 2020-03-25 22:37:55 回复(0)
唔,写了好久。。。
while True:
    try:
        N=int(input())
        if N==0:
            break
        s=[]
        #s为最后输出结果
        sta=[]
        #sta列表储存被替换字符串的模板,长度恒为N,即输入N后的N行
        for n in range(N):
            s.append(input())
            sta.append(s[n])
        for c in s[0]:#找到特殊字符
            if c != ' ':
                ch=c
                break
        Q=int(input())
        lines=N**Q
        for i in range(1,Q):#eg: 3(N)^3(Q) 分解为 3*9 替换
            Len=N**i
            '''每次替换总行数
               Q=2时仅循环一次(i=1),替换N行,
               Q=3时最后一次循环(i=2)替换N^2行'''
            ex=[]
            '''ex列表储存替换字符串的模板
               eg:Q=3时最后一次(i=2),ex有9个元素
               先找到sta[0]中的空格,将其替换成最后输出N^(Q-1)个空格
               再将上述得到的字符串中出现的特殊字符(eg:'#')换为ex[0]
               得到s[0],如此循环N^(Q-1)遍
               再找到sta[1]中的空格,……以此类推
               sta[N-1]……
               得到s[N^Q],即N*N^(Q-1)
            '''
            str0=""
            for h in range(Len):
                str0+=' '#生成一个字符串,包含Len个空格
            for j in range(N): 
                for k in range(Len):
                    if j==0:
                        ex.append(s[k])
                        s[k]=sta[j].replace(' ',str0)
                    else:
                        s.append(sta[j].replace(' ',str0))
                    str1=ex[k]
                    s[k+j*Len]=s[k+j*Len].replace(ch,str1)
                    
        for l in range(lines):#s(最后输出结果),有N^Q行
            print(s[l])
    except:
        break

发表于 2018-08-07 22:04:06 回复(0)
#include<iostream>
using namespace std;
#include<cmath>
#include<vector>
 
char picture[6][6];
int n;
int Q;
 
void  draw(vector<vector<char>> v)
{
    for (vector<vector<char>>::iterator it=v.begin();it!=v.end();it++)
    {
        for (vector<char>::iterator itx = (*it).begin(); itx != (*it).end(); itx++)
        {
            cout << *itx;
        }
        cout << endl;
    }
}
void showPicture(int n, char p[][6], int m, vector<vector<char>> &v)
{
    static int start1 = 0;
    static int start2 = 0;
    int begin1 = start1;
    int begin2 = start2;
 
    if (m == 1)
    {
        for (int i1 = start2,i2=0; i1 < start2+n,i2 < n; i1++,i2++)
        {
            for (int j1 = start1,j2=0; j1 < start1+n,j2 < n; j1++,j2++)
            {
                v[i1][j1] = p[i2][j2];
            }
        }
    }
    else
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (p[i][j] != 32)
                {
                   showPicture(n, p, m - 1,v);
                }
                start1 += pow(n,m-1);
            }
            start1 = begin1;
            start2 += pow(n,m-1);
        }
        start2 = begin2;
    }
}
 
int main()
{
    n = 1;
    Q = 1;
    while (n)
    {
        cin >> n;
 
        cin.ignore();//跳过回车
        for (int i = 0; i < n; i++)
        {
            cin.getline(picture[i], 6);
         }
 
        cin >> Q;
 
        vector<vector<char>> v(pow(n, Q), vector<char>(pow(n, Q), ' '));
 
        showPicture(n,picture,Q,v);
 
        draw(v);
 
        v.clear();
    }
    return 0;
}

递归
编辑于 2020-04-20 09:29:20 回复(0)
以输入的图案作为对比,规模每增加1,就遍历一遍输入的图案,每遍历到其中非空格的字符,就将其映射到对应当前规模的区域中;空格则映射区域均为空格。
映射方法为:取左上角区域作为基础图案,将基础图案复制到对应位置的相同大小区域中。
按照如上映射方法完成一次遍历后,基础图案与映射区域都增大相同倍数,重复上述操作,直到达到要求的规模。
#include<iostream>
using namespace std;

int main(){
	int N,Q;
	char res[1000][1000];
	while(cin>>N){
		getchar();
		if(N==0)
			return 0;
		else{
			for(int i=0;i<N;i++){
				if(!cin.getline(res[i],N+1))
        			cout << "error" << endl;
			}
			char src[N][N];
			for(int i=0;i<N;i++)
				for(int j=0;j<N;j++)
					src[i][j]=res[i][j];	//src作为输入图案进行比对,将迭代结果输出到res中 
			bool flag=0;
			if(res[0][0]==' ')	//flag用来标识首字符是否为空格 
				flag=1;
			cin>>Q;
			int bound=N;
			for(int i=1;i<=Q;i++){	//i表示迭代次数=当前规模 
//基础图案的每个字非空格符映射一个新的基础图案,空格则映射为基础图案大小的空格(取左上角区域为基础图案) 
				for(int j=0;j<N;j++){
					for(int k=0;k<N;k++){
						if(src[j][k]!=' '||(flag==1&&j==0&&k==0)){	//对于基础图案的字符,若其不是空格或者首字符为空格,则将其映射 
							int a=0;
							for(int l=j*bound;l<(j+1)*bound;l++){
								int b=0;
								for(int m=k*bound;m<(k+1)*bound;m++){
									res[l][m]=res[a][b];	//二维数组左上角区域作为基础图案 
									b++;
								}
								a++;
							}
							if(flag&&i>1&&!(j==0&&k==0)){	
//对于首个字符为空格的基础图案,除第一个外,将所有基础图案的左上角变成空格(保留第一个用于下次迭代)
								for(int l=j*bound;l<j*bound+bound/N;l++){
									for(int m=k*bound;m<k*bound+bound/N;m++){
										res[l][m]=' ';
									}
								}
							}
						}
						else{
							int a=0;
							for(int l=j*bound;l<(j+1)*bound;l++){
								int b=0;
								for(int m=k*bound;m<(k+1)*bound;m++){
									res[l][m]=' ';
									b++;
								}
								a++;
							}
						}
					}
				}
				if(flag){	//若首字符为空格,每次迭代都将其左上角区域还原成空格,以保持下轮外层迭代的基础图案正确 
					for(int l=0;l<bound/N;l++){
						for(int m=0;m<bound/N;m++){
							res[l][m]=' ';
						}
					}
				}
				bound*=N;
			}
			for(int i=0;i<bound/N;i++){	//输出迭代后图案 
				for(int j=0;j<bound/N;j++)
					cout<<res[i][j];
				cout<<endl;
			}
		}
	}
} 


发表于 2020-03-02 14:32:11 回复(0)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;

char map[3003][3003];
char str[6][6];
int n;

void dfs(int m, int x, int y){
    if (m == 1){
        for (int i = 0; i<n; i++)
            for (int j = 0; j<n; j++)
                map[x + i][y + j] = str[i][j];
        return;
    }
    int size = (int)pow(n*1.0, m - 1);
    for (int i = 0; i<n; i++){
        for (int j = 0; j<n; j++){
            if (str[i][j] != ' ')
                dfs(m - 1, x + i*size, y + j*size);
        }
    }
}


int main(void){
    n = 1;
    while (n){
        cin >> n;
        getchar();
        for (int i = 0; i < n; i++){
            cin.getline(str[i],6);
        }
        int m;
        cin >> m;
        int size = (int)pow(n*1.0, m);
        for (int i = 0; i<size; i++){
            for (int j = 0; j<size; j++)
                map[i][j] = ' ';
            map[i][size] = '\0';
        }
        dfs(m, 0, 0);
        for (int i = 0; i<size; i++)
            cout<<map[i]<<endl;
    }
    return 0;
} 

发表于 2018-09-15 14:19:07 回复(3)
/**
参考高赞的回答,适当的加了一些解释
题解思路:通过dfs找到每一个子图的左上角的起始点,然后在每一个元图像上面作画。
*/
#include <iostream>
#include <math.h>

using namespace std;

char str[6][6];
char map[3001][3001];
int n;

int IntPow(int x,int n){
    int ans=1;
    for(int i=1;i<=n;i++)
        ans*=x;
    return ans;
}

void dfs(int x,int y,int level){//x,y为子图形的左上角起始点
    if(level==1){//搜索到了基础图形级别
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                map[x+i][y+j]=str[i][j];
            }
        }
        return;
    }
    int Size = IntPow(n,level-1);
    for(int i=0;i<n;i++){//搜索每一个位置对应的缩放的位置
        for(int j=0;j<n;j++){
            if(str[i][j]!=' ')
                dfs(x+i*Size,y+j*Size,level-1);
        }
    }

}

void dfs1(int m, int x, int y){
    if (m == 1){
        for (int i = 0; i<n; i++)
            for (int j = 0; j<n; j++)
                map[x + i][y + j] = str[i][j];
        return;
    }
    int size = (int)pow(n*1.0, m - 1);
    for (int i = 0; i<n; i++){
        for (int j = 0; j<n; j++){
            if (str[i][j] != ' ')
                dfs1(m - 1, x + i*size, y + j*size);
        }
    }
}

int main()
{
    int m;
    while(cin >> n){
        if(n==0)break;
        getchar();
        for (int i = 0; i < n; i++){
            cin.getline(str[i],6);
        }
        int m;
        cin >> m;
        int size = (int)pow(n*1.0, m);
        for (int i = 0; i<size; i++){
            for (int j = 0; j<size; j++)
                map[i][j] = ' ';
            map[i][size] = '\0';
        }
        dfs(0,0,m);
        for(int i=0;i<size;i++){
            cout<<map[i]<<endl;
        }
    }
    return 0;
}

发表于 2019-04-06 10:26:36 回复(0)
参考高赞回答,这递归最开始我都没有写出来呜呜呜,膜拜大佬~
#include<iostream>
#include<vector>
#include <cmath>
using namespace std;

int N = 0; //ImageSpecification
int n = 0; //MagnificationFactor
vector <vector<char>>OriginalMatrix;
vector <vector<char>>EnlargeMatrix;

void DFS(int x, int y, int scale) {//OriginalMatrix做为元图像对EnlargeMatrix进行填充,每次填充从待填充位置的左上角(x,y)开始
	if (scale == 1) {
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < N; ++j) {
				EnlargeMatrix[i + x][j + y] = OriginalMatrix[i][j];//看作对坐标i,j进行偏移后的填充
			}
		}
		return;
	}
	int second_scale = pow(N, scale - 1);//次级图像规模
	for (int i = 0; i < N; i++) {//表明DFS次级图像填充原级图像的相对填充位置,递归降级
		for (int j = 0; j < N; j++) {
			if (OriginalMatrix[i][j] != ' ') {
				DFS(x + i * second_scale, y + j * second_scale, scale - 1);
			}
		}
	}
}

int main() {
	while (cin >> N) {
		OriginalMatrix.clear();
		OriginalMatrix.resize(N, vector<char>(N));
		cin.ignore();//cin 默认情况下是以换行符 \n 作为输入结束的标志
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < N; ++j) {
				OriginalMatrix[i][j] = cin.get();//()中内容必须为字符变量,表示从输入流中读取到()变量中,如果()中没有内容,直接返回数据的值//
			}
			cin.ignore();
		}
		cin >> n;
		EnlargeMatrix.clear();
		EnlargeMatrix.resize((int)pow(N, n), vector<char>((int)pow(N, n)));
		for (int i = 0; i < (int)pow(N, n); ++i) {//先把待输出矩阵的元素全部填充为空格
			for (int j = 0; j < (int)pow(N, n); ++j) {
				EnlargeMatrix[i][j] = ' ';
			}
		}
		DFS(0, 0, n);
		for (int i = 0; i < (int)pow(N, n); ++i) {
			for (int j = 0; j < (int)pow(N, n); ++j) {
				cout << EnlargeMatrix[i][j];
			}
			cout << endl;
		}
	}
}

编辑于 2024-01-19 12:03:51 回复(0)
真心得吐槽牛客网,那个自测有问题,大火不要再自测上浪费时间,自己在自己的IDE上运行,没问题就可以了,直接提交
发表于 2022-02-11 17:05:31 回复(0)
其实只要分析一下放大后的图形一个点的坐标和原来模板中对应的点的坐标就可以发现,放大后的坐标是,其中i表示的是放大倍数(i>1),x'和y'表示的是上一次放大后的坐标,x0和y0表示模板中的对应点,n表示模板的大小。所以想要得到最后的结果,就在每一次放大时,将上一次的结果和模板中的所有点做上面的运算,这样就可以达到该点在放大后对应位置的坐标。
#include<iostream>
#include<vector>
#include<cctype>
#include<cmath>
using namespace std;

struct Point
{
    int x, y;
    Point(int a, int b) : x(a), y(b){};
};


int main(void) {
    int n, time;        // 模板大小、放大倍数
    char str[6][6];     // 存储模板
    while(cin>>n){
        vector<Point> origin;   //模板坐标
        vector<Point> result;   //最终结果坐标
        vector<Point> temp;
        char c;                 //提取模板中的字符

        cin.ignore(6, '\n');    // 清空输入流中的换行
        for (int i = 0; i < n; i++){
            cin.getline(str[i], 6); 
        }
        // 将输入的模板字符数组转换成坐标
        for (int i = 0; i < n; i++){
            for (int j = 0; j < n; j++){
                if(isgraph(str[i][j])){
                    origin.push_back(Point(i, j));
                    c = str[i][j];
                }
                    
            }
        }

        cin >> time;
        result.assign(origin.begin(), origin.end());
        // 开始放大,每放大一倍,结果坐标就和模板坐标卷积一次
        for (int i = 1; i < time; i++){
            for (vector<Point>::iterator it_origin = origin.begin(); it_origin < origin.end(); it_origin++){
                for(vector<Point> ::iterator it_result = result.begin(); it_result<result.end(); it_result++){
                    temp.push_back(Point((*it_result).x + (*it_origin).x * pow(n, i), (*it_result).y + (*it_origin).y * pow(n, i)));
                }
            }
            result.clear();     // 先将result清空。然后再和temp交换
            result.swap(temp);  // 现在result中就是最新的值,然后temp为空
        }

        // 创建最后的画布
        int dime = pow(n, time);
        char **paint = new char*[dime+1];
        for (int i = 0; i < dime; i++)
            paint[i] = new char[dime+1]{' '};

        // 根据坐标填充画布
        for(vector<Point> ::iterator it = result.begin(); it<result.end(); it++){
            paint[(*it).x][(*it).y] = c;
        }
        
        // 打印画布
        for (int i = 0; i < dime; i++){
            for (int j = 0; j < dime; j++){
                if(isgraph(paint[i][j]))
                    cout << c;
                else
                    cout << " ";
            }
            cout << endl;
        }
    }
}


发表于 2020-09-16 23:35:52 回复(0)
没人吐槽这题的输入有问题吗,说好的
# #
 # 
# #
调试器调试时也确实是这样输入的,但实际运行时,第二行最后一个空格直接给你省了,无语
编辑于 2024-04-01 16:16:34 回复(0)

使用了递归的方法

题目的关键在于确定最后打印的位置,我们可以分步确定,这是一种分形图像,对于每个层次(忽略局部)的图像,我们都知道在哪些地方绘画,通过递归的方法,一层层传递,将位置从整体传递到具体的局部,最终得到答案。

#include <iostream>
#include <cmath>
#include <vector>

using namespace std;

void paint_to_array(int n, int size, int begin_row, int begin_col,
                    vector<vector<char>>& template_array,
                    vector<vector<char>>& painting_array);

void paint_to_array(int n, int size, int begin_row, int begin_col,
                    vector<vector<char>>& template_array,
                    vector<vector<char>>& painting_array) {
    if (size == n) {
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                painting_array[begin_row + i - 1][begin_col + j - 1] = template_array[i][j];
            }
        }
        return;
    } else {
        int next_size = size / n;

        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (template_array[i][j] != ' ') {
                    int next_begin_row = begin_row + (i - 1) * next_size;
                    int next_begin_col = begin_col + (j - 1) * next_size;

                    paint_to_array(n, next_size, next_begin_row, next_begin_col, template_array,
                                   painting_array);
                }
            }
        }
    }
}

int main() {
    int n = 0, m = 0;
    while (cin >> n) {
        if (n == 0) {
            break;
        }
        vector<vector<char>> template_array(n + 1, vector<char>(n + 1, ' '));

        char temp;
        cin.get(temp);
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                cin.get(temp);
                template_array[i][j] = temp;
            }
            cin.get(temp);
        }

        cin >> m;
        int painting_size = pow(n, m);

        vector<vector<char>> painting_array(painting_size + 1,
                                            vector<char>(painting_size + 1, ' '));

        paint_to_array(n, painting_size, 1, 1, template_array, painting_array);

        for (int i = 1; i <= painting_size; ++i) {
            for (int j = 1; j <= painting_size; ++j) {
                cout << painting_array[i][j];
            }
            cout << endl;
        }
    }
}
编辑于 2024-03-19 18:53:26 回复(0)
写了两天,被困在了getline(),cin.get(),cin.getline(),scanf(),getchar(),
终于,用getline读取第一个数字完美解决。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
using namespace std;
string temp[5];
char base[5][6];//原模式
char load[1500][1500];//输出
char load_1[1500][1500];//输出
int len;//load中的原复制区域,因为是正方形矩阵,所以是len*len
int n, q; //原模式大小和放大倍数
bool isempty;//原模式是否空
bool swichto = false;//切换原复制区,因为放大一倍后原复制区域会发生变化
void copytoload(int a, int b) { //迭代复制器
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < len; j++) {
            if (swichto) {
                if (!isempty)
                    load[a + i][b + j] = load_1[i][j];

                else load[a + i][b + j] = ' ';//填空白
            } else {
                if (!isempty)
                    load_1[a + i][b + j] = load[i][j];

                else load_1[a + i][b + j] = ' ';//填空白
            }
        }
    }
}

void position(int i, int
              j) { //迭代位置复制器,i j 为源模式的位置,e为目前倍数
    copytoload(len * i, len * j);

}

void initbase() {
    //初始化空格
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            base[i][j] = ' ';
        }
    }
    //从string 转移
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < temp[i].size(); j++) {
            base[i][j] = temp[i][j];
            
        }
        // cout<< "the string length is :" << temp[i].size()<<endl;
    }
}

//把原模式复制到第一块放大版中
void inittoload() {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            load[i][j] = base[i][j];
        }
    }

}



int main() {
    string trans;
    while (true) {
        // scanf("%d\n", &n) != EOF
        getline(cin, trans);//我发现使用getline的时候,如果第一个getline()读取的第一个字符为空格,这个空格就会被丢弃,在这里用getline(),那么下一个读入原模式的getline()就可以读入空格了。
        n=(int)trans[0]-'0';
        // cout << n<<endl;
        if (n < 3) {
            return 0;
        }

        //确保load开始
        swichto = false;

        for (int i = 0; i < n; i++) {
            getline(cin, temp[i]);
        }

        initbase();
        inittoload();
        scanf("%d\n", &q);

        // // 数据检验
        // for (int i=0; i<n; i++) {
        //     for (int j=0; j<n; j++) {
        //         cout<< load[i][j];
        //     }
        //     cout << endl;
        // }
        // cout << "@@@@@@@" << endl;


        //迭代复制
        for (int i = 1; i <= q; i++) { //i为放大倍数,迭代
            len = pow(n, i); //计算原复制区大小
            //从源模式开始判断复制
            for (int a = 0; a < n; a++) {
                for (int b = 0; b < n; b++) {
                    if (base[a][b] != 32 )
                        isempty = false;
                    else isempty = true;
                    position(a, b);
                }
            }
            swichto = !swichto;//切换复制板
        }
        

        //输出
        if (swichto)
            for (int i = 0; i < len; i++) {
                for (int j = 0; j < len; j++) {
                    cout << load[i][j];
                }
                cout << endl;
            } 
        else             
            for (int i = 0; i < len; i++) {
                for (int j = 0; j < len; j++) {
                    cout << load_1[i][j];
                }
            cout << endl;
            }
        // cout << "@@@@@@@" << endl;
        
    }


}


发表于 2024-03-18 21:21:56 回复(0)
#include <cstdio>
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
string mini[5];
char pattern[3000][3000],pattern1[3000][3000];
void bigger(int n,int q) {
    if (q == 1) {
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j)
                pattern1[i][j] = mini[i][j];
        return;
    }
    if (q > 1) bigger(n, q - 1);
    int nowN = pow(n, q - 1), x = 0, y = 0;
    for (int i = 0; i < nowN; ++i) {
        for (int j = 0; j < nowN; ++j) {
            if (pattern1[i][j] != ' ') {
                for (int q = x; q < x + n; ++q)
                    for (int s = y; s < y + n; ++s)
                        pattern[q][s] = mini[q - x][s - y];
            } else {
                for (int q = x; q < x + n; ++q)
                    for (int s = y; s < y + n; ++s)
                        pattern[q][s] = ' ';
            }
            y += n;
        }
        x += n;
        y = 0;
    }
    nowN *= n;
    for (int i = 0; i < nowN; ++i)
        for (int j = 0; j < nowN; ++j)
            pattern1[i][j] = pattern[i][j];
}
int main() {
    int n, q;
    while (scanf("%d", &n) != EOF) {
        if (n == 0) break;
        getchar();
        for (int i = 0; i < n; ++i) getline(cin, mini[i]);
        scanf("%d", &q);
        bigger(n, q);
        for (int i = 0; i < pow(n, q); ++i) {
            for (int j = 0; j < pow(n, q); ++j) {
                printf("%c", pattern1[i][j]);
            }
            printf("\n");
        }
    }
}

发表于 2024-02-11 16:11:12 回复(1)
/*
题目翻译:
描述:
和谐在我们的日常生活中是不可或缺的,
任何人都离不开它——也许Facer是唯一的例外。
有一天,有传言说重复绘画会创造和谐,然后数百人开始了他们无尽的绘画。
他们的画是以一个小模板和一种简单的复制方法为基础的。
虽然Facer很容易想象出整个画面的风格,但他找不到本质上的和谐。
现在你需要通过在电脑上显示图片来帮助Facer。
你会得到一个只包含一种字符和空间的模板,
该模板显示了无尽的画面是如何创建的——将字符作为基本元素,
并将它们放在正确的位置,以形成一个更大的模板,然后重复。
这是一个例子。###<-模板##
所以第1级图片将是######第2级图片将为#############
输入描述:
输入包含多个测试用例。
每种情况的第一行是整数N,表示模板的大小为N*N(N只能是3、4或5)。
接下来的N行描述模板。下一行包含一个整数Q,它是图片的缩放级别。
输入以N=0的情况结束。保证一张图片的大小不超过3000*3000。
输出描述:
对于每个测试用例,只需使用给定的模板打印Q级图片即可。
*/
#include <array>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

//自定义数据类型
using Matrix = array<array<char, 3000>, 3000>;  //字符矩阵
using SmallMatrix = vector<string>; //字符小矩阵(为节省空间)

//全局变量
Matrix picture, oldPicture;     //用矩阵存储图形
SmallMatrix originalTemplate;   //原始图形模板
int size, oldSize;  //矩阵大小(行数和列数)

//将矩阵m1的内容复制到矩阵m2,复制起点的行列下标为i和j,矩阵大小为size
void copyMatrix(Matrix m1, Matrix& m2, int i, int j, int size) {
    for (int a = 0; a < size; a++) {
        for (int b = 0; b < size; b++) {
            m2[i + a][j + b] = m1[a][b];
        }
    }
}

//将矩阵m的内容清空为空格(用空格填充),矩阵大小为size
void clearMatrix(Matrix& m, int size) {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            m[i][j] = ' ';
        }
    }
}

//绘图函数,绘制出的图形以字符矩阵形式存储到全局变量picture中
//oldPicture存储前一次函数调用绘制的图形
void draw(int n, int q) {
    if (q == 1) {
        ::size = n;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                picture[i][j] = originalTemplate[i][j];
            }
        }
        return;
    }
    draw(n, q - 1); //递归调用绘图函数
    copyMatrix(picture, oldPicture, 0, 0, ::size);
    oldSize =::size;
    ::size *= n;
    clearMatrix(picture, ::size);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (originalTemplate[i][j] != ' ') {
                copyMatrix(oldPicture, picture,
                           i * oldSize, j * oldSize, oldSize);
            }
        }
    }
}

int main() {
    int n, q;
    while (cin >> n && n != 0) {
        getchar();  //吃掉回车
        originalTemplate.clear();   //清空矩阵
        for (int i = 0; i < n; i++) {   //读取模板
            string str;
            getline(cin, str);
            originalTemplate.push_back(str);
        }
        cin >> q;
        draw(n, q); //绘制图形
        for (int i = 0; i <::size; i++) {
            for (int j = 0; j <::size; j++) {
                cout << picture[i][j];
            }
            cout << endl;
        }
    }
    return 0;
}

编辑于 2024-02-01 10:13:16 回复(0)
#include<stdio.h>
#include<math.h>
using namespace std;

char tpl[5][5];
char picture[3000][3000];

void draw(int n, int q, int x, int y){
	if(q == 1){
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
				picture[x + i][y + j] = tpl[i][j];
			}
		}
	}else{
		int length = pow(n, q - 1);
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
				if(tpl[i][j] != ' '){
					draw(n, q - 1, x + i * length, y + j * length);
				}
			}
		}
	}
}

int main(){
	int n, q;
	scanf("%d", &n);
	while(n != 0){
		getchar();
		char ch;
		for(int i = 0; i < n; i++){
			int j = 0;
			while((ch = getchar()) != '\n'){
				tpl[i][j] = ch;
				j++;
			}
		}
		scanf("%d", &q);
		
		for(int i = 0; i < 3000; i++){
            for(int j = 0; j < 3000; j++){
                picture[i][j] = ' ';
            }
        }
		draw(n, q, 0, 0);
		
		int len = pow(n, q);
		for(int i = 0; i < len; i++){
			for(int j = 0; j < len; j++){
				printf("%c", picture[i][j]);
				//picture[i][j] = ' ';
			}
			printf("\n");
		}
		scanf("%d", &n);
	}
	
	return 0;
}
有哪位大佬能帮忙分析一下:
        我这段代码用的递归,仿照“题解”顶楼大佬来的,代码如上,但是遇到了一个莫名其妙的问题:第42到46行,我本来想用第53行替代,在本地上也能跑通,但是在牛客上就是不通过,各种乱七八糟的报错,样例是只跑出来2行就停了,提交的话显示好像一行输出都没有。我换成42到46行,然后就过了。这是为什么?难道牛客网默认二维数组没初始化就不能直接用?
编辑于 2024-01-27 12:19:44 回复(0)
#include <bits/stdc++.h>

using namespace std;

int N;
char origin[5][5];
char pic[3010][3010];

void draw(int Q, int x, int y) {
    if(Q == 1) {
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < N; j++) {
                if(origin[i][j] != ' ') {
                    pic[x+i][y+j] = origin[i][j];
                }
            }
        }
    } else {
        int size = pow(N,Q-1);
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < N; j++) {
                if(origin[i][j] != ' ') {
                    draw(Q-1, x+i*size, y+j*size);
                }
            }
        }
    }
}

int main() {
    while(scanf("%d",&N)) {
        if(N == 0) break;
        getchar();
        for(int i = 0; i < 3010; i++) {
            for(int j = 0; j < 3010; j++) {
                pic[i][j] = ' ';
            }
        }
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < N; j++) {
                origin[i][j] = getchar();
            }
            getchar();
        }
        int Q;
        scanf("%d",&Q);
        draw(Q,0,0);
        int len = (int) pow(N,Q);
        for(int i = 0; i < len; i++) {
            for(int j = 0; j < len; j++) {
                cout << pic[i][j];
            }
            cout << endl;
        }
    }
    return 0;
}

发表于 2023-08-13 15:58:54 回复(0)