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 :
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.
Sample Input
1234-1
Sample Output
X-X X XX X-X X X X X XX X X X X X X X XX X X X X XX X X X-X X X X X X X X X X X XX X X X X X X X X X X X X X X X X XX X X X X X X X X X X XX X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X XX X X X X X X X X X X XX X X X X X X X X X X X X X X X X XX X X X X X X X X X X XX X X X X X X X
一遞迴:
先看下較為常規的遞迴解決:
由於圖形是重複的,小的圖形只是把大圖形的左上方一部分輸出,,只計算最大的圖形,打表可加快速度。
#include <stdio.h>#include <string.h>int p[8] = {1,3,9,27,81,243,729};char map[730][730];//n當前的圖形大小,x,y圖形所在的座標void print(int n,int x,int y){if(n == 0){map[x][y] = 'X'; //return;}print(n-1, x, y); //左上print(n-1, x+2*p[n-1], y); //右上print(n-1, x+p[n-1], y+p[n-1]); //中間print(n-1, x, y+2*p[n-1]);print(n-1, x+2*p[n-1], y+2*p[n-1]);}int n;int main(){for(int i=0; i<p[6]; i++) memset(map[i], 32, p[6]);print(6, 0, 0); //打表while(scanf("%d", &n) && n-- >= 0){for(int i=0; i<p[n]; i++){map[i][p[n]]=0;puts(map[i]);map[i][p[n]]=' ';}puts("-");}return 0;}
二 數學方法
在discuss裡面看到這個短小精悍的程式。
#include"stdio.h"#include"math.h"main(){int i,j,n,ii,jj,k;while(scanf("%d",&n)&&n--!=-1){for(i=0;i<pow(3,n);i++,printf("\n"))for(j=0;j<pow(3,n);j++){for(ii=i,jj=j,k=0;k<n&&(ii%3+jj%3)%2==0;ii/=3,jj/=3,k++);printf("%c",32+56*(k==n));}printf("-\n");} }
以下摘自 http://www.matrix67.com 部落格:
關於這個圖形,還可以用來證明
尋找1/5
+ 1/25 + 1/125 + .. = 1/4的圖形證明
前段時間,網上湧現出一大批關於1/4 + 1/16 + 1/64 + ... = 1/3的圖形證明(1) (2)。不過,有多少人想過,為什麼這些圖形都是證明底數為1/4的情況呢?同樣是幾何級數求和,能否構造一個圖形來證明1/5
+ 1/25 + 1/125 + .. = 1/4呢?
無妨讓我們來嘗試一下。絕大多數人的第一想法便是畫一個正五邊形,然後把它分成五等分。接下來,把其中一份塗上顏色,表示整個面積的1/5。然後呢?然後怎麼辦?我們需要有一種辦法把剩下的四塊中的其中一塊再次分成五份,選取一份表示1/25,並且遞迴地做下去。我們似乎發現了問題:這個“遞迴”是做不下去的。為了能夠遞迴地表示出1/5、1/25、1/125,你必須把一個正五邊形分成五個小的正五邊形,再把小正五邊形分成更小的五個正五邊形,而這似乎是做不到的。這也就是上面的那些圖形都可以用來證明Σ(1/4)^n=1/3的根本原因:它們可以把自己分成更小的四個自己,從而能夠遞迴地表示(1/4)^n。
現在,我們的問題就出來了:為了弄出一個Σ(1/5)^n=1/4的圖形證明,我們必須尋找這樣一種圖形,它能把自身分割為五塊相同的部分,每一部分都和自身相似。
我們能否找到這樣的圖形呢?不能!根本原因在於:一個平面圖形是二維的。平面圖形的維度決定了這樣一個性質:兩個相似圖形的相似比和面積比成平方關係。如果一個正方形的邊長是另一個正方形邊長的兩倍,那前者的面積就是後者的四倍;圓的面積必然與半徑r成平方關係,最多再乘上一個常係數。類似地,把一條曲線放大一倍,其長度也會跟著變大一倍;把一個三維圖形放大一倍,其體積將變大到原來的八倍。因此,把一個平面圖形分成四個和自身相似的圖形是相當和諧的——面積變為原來的1/4,邊長就應該變為原來的1/2,而兩個1/2邊長正好就拼成一個原邊長。但是,如果要想把一個平面圖形分成五等份,每一份的面積就應該是1/5,則對應邊應該變為原來的1/sqrt(5),這樣顯然無法既無重複又無遺漏地填滿原圖形的邊。看來,圖形證明Σ(1/5)^n=1/4似乎就不可能了。
思考問題時要善於用想象來替代放棄。二維空間中可以證明Σ(1/4)^n=1/3。類似地,一維空間中還可以輕易證明Σ(1/2)^n=1。要是有一個什麼東西是log(5)/log(2)維的就好了——這樣的話,對應邊擴大到原來的2倍,“面積”就會變成原來的2^(log(5)/log(2))倍,也就是5倍。這就是說,在log(5)/log(2)維的“空間”裡,一個“圖形”恰好可以包含5個與自身相似的“圖形”,並且新的“邊長”正好能整除原來的“邊長”。看到這裡有人會哈哈大笑起來——這種維度會有嗎?
有。很多分形圖形都有一些極其怪異的性質,相似比的變化和其所佔空間的變化不成整次冪的關係。例如,大名鼎鼎的分形圖形Sierpinski三角形就是這樣——相似比為1/2,所佔空間之比為1/3。一個圖形有二維圖形的樣子,卻沒有二維圖形的性質。Hausdorff維度就是專門用來處理這類問題的。我們常常用Hausdorff維度來描述一個分形圖形,比如Sierpinski三角形的Hausdorff維度就是log(3)/log(2)——所佔面積變為原來的三倍時,對應邊變為原來的兩倍。
嘿!那麼,是不是Sierpinski三角形就可以用來證明Σ(1/3)^n=1/2呢?對!一個Sierpinski三角形由三個與自身相似的小Sierpinski三角形組成,因此你可以遞迴地表示出(1/3)^n。畫出整個Sierpinski三角形的1/3,以及另外1/3的其中1/3,以及1/3的1/3的1/3,這樣無限畫下去,你會很快看出來,總地區正好佔了原來的一半。
類似地,把Sierpinski地毯放大到原來的三倍,整個圖形所佔空間就變成了原來的八倍。它的Hausdorff維度就是log(8)/log(3)。於是,我們就能用它來證明Σ(1/8)^n=1/7。
回到本文最初的問題,為了證明Σ(1/5)^n=1/4,我們只需要找到這樣一個分形圖形,其Hausdorff維度分子為log(5)。這樣的圖形不僅存在,而且還不止一個。大家可以在這個頁面裡找到各種不同Hausdorff維度圖形。我找到了一個有趣的分形圖形叫做Vicsek雪花,它的Hausdorff維度是log(5)/log(3)。
不斷選出更小意義上的那個1/5,你會一眼看出,選出部分的總和就是整個圖形的1/4。