目录
例题一 “The Sierpinski Fractal”
例题二 “文件结构“图””
例题一 “The Sierpinski Fractal”
【描述】
考虑一个规则的三角形区域,将其划分为四个相等的一半高度的三角形,然后将中间的三角形去除。对剩余的三个三角形中的每个递归地应用相同的操作。如果无限次重复此过程,则将获得面积为零的东西。以这种方式演化的分形称为Sierpinski三角形。尽管其拓扑维数为2,但其Hausdorff-Besicovitch维数为log(3)/ log(2)〜1.58,是一个分数值(这就是为什么它称为分形)。顺便说一下,挪威海岸的Hausdorff-Besicovitch维度约为1.52,其拓扑维度为1。
对于此问题,您将仅使用ASCII字符将Sierpinski三角形的轮廓绘制到一定的递归深度。由于绘图分辨率是固定的,因此您需要适当地放大图片。用两个斜杠绘制最小的三角形(不再进一步划分),以反斜杠和两个下划线表示,如下所示:
/\
/__\
要查看如何绘制更大的三角形,请看一下示例输出。
【输入】
输入包含几个测试用例。每个由整数n指定。输入以n = 0终止。否则,1 <= n <= 10表示递归深度。
【输出】
为每个测试用例绘制一个Sierpinski三角形的轮廓,其侧面的总长度为2 n个字符。将您的输出向左对齐,即,将最左下的斜线打印到第一列中。输出中不得包含任何尾随空白。在每个测试用例之后打印一个空行。
【样例输入】
3
2
1
0
【样例输出】
/\
/__\
/\ /\
/__\/__\
/\ /\
/__\ /__\
/\ /\ /\ /\
/__\/__\/__\/__\
/\
/__\
/\ /\
/__\/__\
/\
/__\
【来源】OJ
【解】
#include <iostream>
#include <cstring>
using namespace std;
void drawL1();//画第一层, 不转行
void drawL2();//画第二层, 不转行
void myDraw(int layer,//级数
int lines_in_layer//第几层,从1开始
);//画出指定级数的图形的指定层,不考虑行前空格和行后换行
void finaldraw(int layer);//包装
int n;
int main() {
while(cin >> n) {
finaldraw(n);
cout << '\n';
}
cin >> n;
}
void drawL1()
{
printf("/\\"); return;
}
void drawL2()
{
printf("/__\\"); return;
}
void myDraw(int layer, int lines_in_layer)
{
if(layer == 0)return;
else if(layer == 1 && lines_in_layer == 1)drawL1();
else if(layer == 1 && lines_in_layer == 2)drawL2();
else {
if(lines_in_layer <= (1 << (layer-1))) {
myDraw(layer - 1, lines_in_layer);
}//上半部分
else {
myDraw(layer - 1, lines_in_layer - (1 << (layer - 1)));
for(int BLANK = 0; BLANK < (((1<<layer)-lines_in_layer)<<1);++BLANK)printf(" ");
myDraw(layer - 1, lines_in_layer - (1 << (layer - 1)));
}//下半部分 中间空格
return;
}
return;
}
void finaldraw(int layer)
{
for(int i = 1; i <= (1 << layer); ++i) {
//前方空格
for(int countBlank = 0; countBlank < (1 << layer) - i; ++countBlank)printf(" ");
myDraw(layer, i);
printf("\n");
}
return;
}
【说明】应恰当地选取可递归的部分。
例题二 “文件结构“图””
【描述】
在计算机上看到文件系统的结构通常很有用。Microsoft Windows上面的"explorer"程序就是这样的一个例子。但是在有图形界面之前,没有图形化的表示方法的,那时候最好的方式是把目录和文件的结构显示成一个"图"的样子,而且使用缩排的形式来表示目录的结构。比如:
ROOT
| dir1
| file1
| file2
| file3
| dir2
| dir3
| file1
file1
file2
这个图说明:ROOT目录包括三个子目录和两个文件。第一个子目录包含3个文件,第二个子目录是空的,第三个子目录包含一个文件。
【输入】
你的任务是写一个程序读取一些测试数据。每组测试数据表示一个计算机的文件结构。每组测试数据以’*‘结尾,而所有合理的输入数据以’#‘结尾。一组测试数据包括一些文件和目录的名字(虽然在输入中我们没有给出,但是我们总假设ROOT目录是最外层的目录)。在输入中,以’]‘表示一个目录的内容的结束。目录名字的第一个字母是’d’,文件名字的第一个字母是’f’。文件名可能有扩展名也可能没有(比如fmyfile.dat
和fmyfile
)。文件和目录的名字中都不包括空格,长度都不超过30。一个目录下的子目录个数和文件个数之和不超过30。
【输出】
在显示一个目录中内容的时候,先显示其中的子目录(如果有的话),然后再显示文件(如果有的话)。文件要求按照名字的字母表的顺序显示(目录不用按照名字的字母表顺序显示,只需要按照目录出现的先后显示)。对每一组测试数据,我们要先输出"DATA SET x:",这里x是测试数据的编号(从1开始)。在两组测试数据之间要输出一个空行来隔开。
你需要注意的是,我们使用一个’|'和5个空格来表示出缩排的层次。
样例输入
file1
file2
dir3
dir2
file1
file2
]
]
file4
dir1
]
file3
*
file2
file1
*
#
【样例输出】
DATA SET 1:
ROOT
| dir3
| | dir2
| | file1
| | file2
| dir1
file1
file2
file3
file4
DATA SET 2:
ROOT
file1
file2
【提示】
一个目录和它的子目录处于不同的层次
一个目录和它的里面的文件处于同一层次
【来源】OJ
【解】
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
//#include<fstream>
using namespace std;
//ofstream fout("D:\\out.txt", ios::trunc);
int display(int layer, string headname="ROOT");//第0层是ROOT
int main() {
//if(!fout) { cerr << "Open Failed.\n"; system("pause"); return 0; }
int count = 1;
bool is_end = false;
while(!is_end) {
cout << "DATA SET " << count << ":\n";
//fout << "DATA SET " << count << ":\n";//
int s=display(0);
if(s == -1) {
//cout << "END success.\n";
is_end = true; break;
}
printf("\n"); //fout << endl;
++count;
}
//fout.close();//
//int n; cin >> n;
}
int display(int layer, string headname)
{
string temp; vector<string> tempL;
//先输出子目录
for(int HEAD = 0; HEAD < layer; ++HEAD) {
cout << "| "; //fout << "| ";
}
cout << headname << endl; //fout << headname << endl;
while(true) {
cin >> temp;
if(temp[0] == '*') { break; }
if(temp[0] == 'd')display(layer + 1, temp);
else if(temp[0] == 'f')tempL.push_back(temp);
else if(temp[0] == ']')break;
}
sort(tempL.begin(), tempL.end());//正常排序
for(vector<string>::iterator i = tempL.begin(); i != tempL.end(); ++i) {
for(int HEAD = 0; HEAD < layer; ++HEAD) {
cout << "| "; //fout << "| ";
}
cout << *i << endl; //fout << *i << endl;
}
if(layer == 0) { //判断是否结束: 看下一个是否为'#'
char c = 0;
getchar();//去掉'\n'
c = cin.peek();
if(c == '#')return -1;
}
return 0;
}
【注】应当恰当选取递归的部分。