算法学习10008(递归)

本文详细探讨了递归算法的概念、工作原理及其实现细节,通过实例解析了递归在解决复杂问题中的应用。同时,讨论了递归算法的优缺点,包括其空间效率和时间复杂度,并提供了避免无限递归的策略。最后,文章介绍了如何将递归转化为迭代,以优化性能。
摘要由CSDN通过智能技术生成
Problem description
A fractal is an object or quantity that displays self-similarity, in a somewhat technical sense, on all scales. The object need not exhibit exactly the same structure at all scales, but the same "type" of structures must appear on all scales.
A box fractal is defined as below :
 
  • A box fractal of degree 1 is simply
    X
     
  • A box fractal of degree 2 is
    X  X
      X
    X  X
     
  • If using B(n - 1) to represent the box fractal of degree n - 1, then a box fractal of degree n is defined recursively as following
     
    B(n - 1)        B(n - 1)
    
            B(n - 1)
    
    B(n - 1)        B(n - 1)

Your task is to draw a box fractal of degree n.

Input
The input consists of several test cases. Each line of the input contains a positive integer n which is no greater than 7. The last line of input is a negative integer −1 indicating the end of input.
Output
For each test case, output the box fractal using the 'X' notation. Please notice that 'X' is an uppercase letter. Print a line with only a single dash after each test case. be careful, no extra blankspace allowed in the output.
Sample Input
1
2
3
4
-1
Sample Output
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
-
 
   在做这道递归的题目时,如果简单得就是在5个位置上递归调用B(n-1)肯定不行,因为光标会落在前一个B(n-1)的最后,而不是第一行指定的位置,查阅了一些光标移动的函数,觉得太麻烦了。
后来想那就用一个大大的数组去保存图形吧,第一块直接调用B(n-1),然后画出中心的图形,最后用行对称和列对称去完成其余三个图形的绘制,对称的思想固然简单,但是严重超时了!
再后来,我想,那既然为了图快,那我就用一个三维数组,把7种图形都提前画好,到时候要哪个就去取哪个,速度就特别的快了。在画图的时候,用draw(x,y,n)在指定的(x,y)起点处画上第n-1
个图形,递归的思想就在每个图的绘制都是利用前一个图去画的(数组的复制memcpy(知道起点,知道终点,知道复制多少个字节即可))。画好以后,为了不输出多余的空格,还要对画好的图形
进行相应的处理(输出时可以按行一行一行地输出,所以在每行最后加上'\0',即字符串终结符,在找到最后一个X时一定要return,不然会一直i--到第一个X,于是我一开始总是只打印出左半部分
的图形!),代码如下,这个效率非常高:

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

//把7种X图形都保存在一个三维数组pic[图形编号][行数][列数],作为全局变量
char pic[7][1000][1000];
int three[11];
/*
int len(int n)
{
	return (int)pow(3,n);
}*/

//在指定位置画图draw(i,j,n)  i:行,j:列, n第几个图形(0到6共7种)
//一共有五块位置,都用数组复制得到
//memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
void draw(int x,int y, int n)
{
	int i;
	for(i=0;i<three[n-1];i++)
	{
		memcpy(&pic[n][x+i][y],&pic[n-1][i][0],three[n-1]);
		/*
		for(j=0;j<three[n-1];j++)
		{
			pic[n][x+i][y+j]=pic[n-1][i][j];

		}*/
	}
}

//由于一开始全部用空格填充三维数组,为了不让多余空格输出,要对数组做一些处理
//找到每一行的最后一个字符
void deal(int x,int y,int len)//y表示行,x表示图形
{
	int i;
	for(i=len;i>-1;i--)
	{
		
		if(pic[x][y][i]=='X')
		{
			pic[x][y][i+1] = '\0';
			<span style="font-size:32px;color:#ff0000;"><strong>return;</strong></span>//天哪!!!!论return的重要性!不然找到了X以后就又i--了,于是就找到了第一个X !!!!
		}
	}
}


void init()
{
	int i,j;
	three[0] = 1;
    for(i = 1; i < 9; i++)
        three[i] = three[i-1] * 3;
	memset(pic,' ',sizeof(pic));
	pic[0][0][0] = 'X';
	
	//把7个图形全部都画出来
	for(i=1;i<7;i++)
	{
		int l = three[i-1];
		
		draw(0,0,i);//左上方
		draw(2*l,0,i);//左下角
		draw(0,2*l,i);//右上方
		draw(2*l,2*l,i);//右下角
		draw(l,l,i);//中间		
	}
	
	for(i=0;i<7;i++)//i表示图形号
		for(j=0;j<three[i];j++)//j表示行
			deal(i,j,three[i]);
} 

//上面把这7种图形已经画好并且保存在三维数组中了,现在就是要打印出来
void main()
{
	int input;
	init();
	int row;
	while(scanf("%d", &input) && input!=-1)
	{
	//int length = len(input-1);
		for(row = 0;row<three[input-1];row++)
			printf("%s\n", pic[input-1][row]);
		printf("-\n");
	}

	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值