If a large sheet of paper is folded in half, then in half again, etc, with all the folds parallel, then opened up flat, there are a series of parallel creases, some pointing up and some down, dividing the paper
into fractions of the original length. If the paper is only opened ``half-way'' up, so every crease forms a 90 degree angle, then (viewed end-on) it forms a ``dragon curve''. For example, if four successive folds are made, then the following curve is seen
(note that it does not cross itself, but two corners touch):

Write a program to draw the curve which appears after N folds. The exact specification of the curve is as follows:

  • The paper starts flat, with the ``start edge'' on the left, looking at it from above.
  • The right half is folded over so it lies on top of the left half, then the right half of the new double sheet is folded on top of the left, to form a 4-thick sheet, and so on, for N folds.
  • Then every fold is opened from a 180 degree bend to a 90 degree bend.
  • Finally the bottom edge of the paper is viewed end-on to see the dragon curve.

From this view, the only unchanged part of the original paper is the piece containing the ``start edge'', and this piece will be horizontal, with the ``start edge'' on the left. This uniquely defines the curve.
In the above picture, the ``start edge'' is the left end of the rightmost bottom horizontal piece (marked `s'). Horizontal pieces are to be displayed with the underscore character ``_'', and vertical pieces with the ``|'' character.

Input

Input will consist of a series of lines, each with a single number N (  ).
The end of the input will be marked by a line containing a zero.

Output

Output will consist of a series of dragon curves, one for each value of N in the input. Your picture must be shifted as far left, and as high as possible. Note that for large N, the picture will
be greater than 80 characters wide, so it will look messy on the screen. The pattern for each different number of folds is terminated by a line containing a single `^'.

Sample input

2
4
1
0

Sample output

|_
 _|
^
   _   _
  |_|_| |_
   _|    _|
|_|
^
_|
^

经典题目吧,感觉是练习递归的,可是有非递归的方式做,果断直接迭代了。

观察每次展开新部分和旧部分,新的尾和旧的头相对应,依次往中间走对应起来,得到对应关系:

上变成左

下变成右

左变成下

右变成上

画图的部分用map存储。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <stack>
#include <queue>
#include <bitset>
#include <cassert>
#include <cmath>
#include <functional>

using namespace std;

const int maxn = 1 << 15;
int A[maxn];

// 0,1,2,3分别是上下左右
int trans[] = { 2, 3, 1, 0 };

map<int, set< pair<int, int> > > P;

void build(int n)
{
	int m = 1;
	A[0] = 3;
	for (int i = 1; i <= n; i++) {
		for (int j = m - 1, k = m; j >= 0; j--, k++) { // 算出下一次展开的位置
			A[k] = trans[A[j]];
		}
		m <<= 1;
	}
	int x = -1, y = 0, px = 0, py = 0;
	P.clear();
	// 把每个短线的位置计算出来,并放入P中
	for (int i = 0; i < m; i++) {
		if (A[i] == 0) {
			x = px << 1;
			y = py;
			P[y].insert(make_pair(x, 0));
			py++;
		}
		else if (A[i] == 1) {
			x = px << 1;
			y = py - 1;
			P[y].insert(make_pair(x, 1));
			py--;
		}
		else if (A[i] == 2) {
			x = (px << 1) - 1;
			y = py;
			P[y].insert(make_pair(x, 2));
			px--;
		}
		else {
			x = (px << 1) + 1;
			y = py;
			P[y].insert(make_pair(x, 3));
			px++;
		}
	}
}

void draw()
{
	// 设置无穷大和无穷小,具体为什么在这篇题解前一篇博文有说明
	int mxy = -0x3f3f3f3f, mnx = 0x3f3f3f3f;
	for (map<int, set< pair<int, int> > >::iterator it = P.begin();
		it != P.end(); it++) {
		mxy = max(mxy, it->first);
		for (set< pair<int, int> >::iterator jt = it->second.begin();
			jt != it->second.end(); jt++) {
			mnx = min(mnx, jt->first);
		}
	}
	// 从最上面一行画起,所以需要反向遍历
	for (map<int, set< pair<int, int> > >::reverse_iterator it = P.rbegin();
		it != P.rend(); it++) {
		int i = mnx;
		for (set<pair<int, int> >::iterator jt = it->second.begin();
			jt != it->second.end(); jt++) {
			while (i < jt->first) {
				cout << ' ';
				i++;
			}
			i++;
			if (jt->second == 0 || jt->second == 1) {
				cout << '|';
			}
			else {
				cout << '_';
			}
		}
		cout << endl;
	}
	cout << '^' << endl;
}

int main()
{
	ios::sync_with_stdio(false);
	int n;
	while (cin >> n && n) {
		build(n);
		draw();
	}

	return 0;
}

Uva - 177 - Paper Folding的更多相关文章

  1. uva 177:Paper Folding(模拟 Grade D)

    题目链接 题意:一张纸,每次从右往左对折.折好以后打开,让每个折痕都自然的呈90度.输出形状. 思路:模拟折……每次折想象成把一张纸分成了正面在下的一张和反面在上的一张.维护左边和方向,然后输出.细节 ...

  2. Paper Folding UVA - 177 模拟+思路+找规律

    题目:题目链接 思路:1到4是很容易写出来的,我们先考虑这四种情况的绘制顺序 1:ru 2:rulu 3:rululdlu 4:rululdluldrdldlu 不难发现,相较于前一行,每一次增加一倍 ...

  3. 【uva 177】Paper Folding(算法效率--模拟)

    P.S.模拟真の难打,我花了近乎三小时!o(≧口≦)o 模拟题真的要思路清晰!分块调试. 题意:著名的折纸问题:给你一张很大的纸,对折以后再对折,再对折--每次对折都是从右往左折,因此在折了很多次以后 ...

  4. UVA 177 PaperFolding 折纸痕 (分形,递归)

    著名的折纸问题:给你一张很大的纸,对折以后再对折,再对折……每次对折都是从右往左折,因此在折了很多次以后,原先的大纸会变成一个窄窄的纸条.现在把这个纸条沿着折纸的痕迹打开,每次都只打开“一半”,即把每 ...

  5. 紫书 习题8-5 UVa 177 (找规律)

    参考了https://blog.csdn.net/weizhuwyzc000/article/details/47038989 我一开始看了很久, 拿纸折了很久, 还是折不出题目那样..一脸懵逼 后来 ...

  6. 【Uva 1630】Folding

    [Link]: [Description] 你能对字符串进行压缩的操作; 即把连续出现的相同的子串改成它出现的次数+这个最基本的字符串的形式; 问你这个字符串最短能被压缩得多短; [Solution] ...

  7. github上所有大于800 star OC框架

    https://github.com/XCGit/awesome-objc-frameworks#awesome-objc-frameworks awesome-objc-frameworks ID ...

  8. 一位学长的ACM总结(感触颇深)

    发信人: fennec (fennec), 信区: Algorithm 标 题: acm 总结 by fennec 发信站: 吉林大学牡丹园站 (Wed Dec 8 16:27:55 2004) AC ...

  9. GitHub前50名的Objective-C动画相关库

    GitHub的Objective-C的动画UI库其实是最多的一部分,GitHub有相当一部分的动画大牛,如Jonathan George,Nick Lockwood,Kevin,Roman Efimo ...

随机推荐

  1. JavaScript 调试

    在编写 JavaScript 时,如果没有调试工具将是一件很痛苦的事情. JavaScript 调试 没有调试工具是很难去编写 JavaScript 程序的. 你的代码可能包含语法错误,逻辑错误,如果 ...

  2. 什么是 Docker

    Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目.它基于 Google 公司推出的 Go 语言实现. 项目后来加入了 Linux 基金会,遵从了 ...

  3. Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析

    原文地址:http://www.javatang.com 一个典型的thread dump文件主要由一下几个部分组成: 上图将JVM上的线程堆栈信息和线程信息做了详细的拆解. 第一部分:Full th ...

  4. iOS关于时间的处理

    转自:iOS关于时间的处理 做App避免不了要和时间打交道,关于时间的处理,里面有不少门道,远不是一行API调用,获取当前系统时间这么简单.我们需要了解与时间相关的各种API之间的差别,再因场景而异去 ...

  5. Git之(四)分支管理

    当我们初始化Git仓库的时候,Git会默认创建一个名为master的主分支.在实际工作中,主分支要求是一个稳定.健壮.安全的主线,一般不允许在主分支上直接进行开发,而是拉取一个新的分支,开发.测试完成 ...

  6. 大话XML解析

    之前我写过一篇关于xml解析的文章:http://blog.csdn.net/sdksdk0/article/details/50749326.今天这篇文章主要是进一步加深对xml基础的理解了使用,毕 ...

  7. logstash分析日志

    待处理日志格式如下: [totalCount: 298006556, count: 287347623, queryCount: 259027994, exeCount: 28319629, tota ...

  8. pdflush的工作原理

    大家知道,在linux操作系统中,写操作是异步的,即写操作返回的时候数据并没有真正写到磁盘上,而是先写到了系统cache里,随后由pdflush内核线程将系统中的脏页写到磁盘上,在下面几种情况下,系统 ...

  9. Android中的语言和字符串资源

    在任何情况下,从您的应用代码中提取 UI 字符串并将其存放在外部文件中都是个好办法.Android 在每个 Android 项目中都提供一个资源目录,从而简化了这一过程. 如果您是使用 Android ...

  10. MySQL 存储过程探秘

    关于存储过程的优点,本文不再阐述.这里只是对创建存储过程时可能遇到的问题做一下简单的分析. 必备基础 这里说的基础,是相关于如何创建一个存储过程的. DELIMITER:分隔符,定界符. 作用就是:作 ...