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

著名的折纸问题:给你一张很大的纸,对折以后再对折,再对折……每次对折都是从右往左折,因此在折了很多次以后,原先的大纸会变成一个窄窄的纸条。现在把这个纸条沿着折纸的痕迹打开,每次都只打开“一半”,即把每个痕迹做成一个直角,那么从纸的一端沿着和纸面平行的方向看过去,会看到一条美妙的曲线。

就是一个分形,规定一下,纸的朝向,然后不难发现规律。

实现方面,可以迭代也可递归。

在图形输出方面,存下x和y坐标,然后下标排个序,或者用map。

//Rey 2015.8.3
#include<bits/stdc++.h>
using namespace std;

// r -> rl -> open -> ru
//   -> rlrl -> open -> r ud l -> open -> ru lu
//   -> rlrlrlrl -> open -> r ud lr ud l -> open -> ru ludr dl -> rulu ldlu
//   -> rlrlrlrlrlrlrlrl -> r ud lr ud lr ud lr ud l -> ru


const int maxn = 14;
const int maxL = (1<<13)+5;
int dir[maxL];
int Rotate[maxL];
int r[maxL];
int x[maxL],y[maxL];
// up right down left
// 0   1    2    3
int dx[] = {-1,0,0, 0};
int dy[] = { 0,1,0,-1};
int mx[] = { 0,0,1, 0};
int my[] = { 0,1,0,-1};
char decode[] = {'|','_','|','_'};

bool cmp(int a,int b) { return x[a] < x[b] || ( x[a] == x[b] && y[a] < y[b] ); }

void solve(int n)
{
    int N = (1<<n);
    // fold
    for(int i = 0, tmp[2] = {1,3}; i < N; i++) dir[i] = tmp[i&1];
    memset(Rotate,0,sizeof(int)*N);
    //open
    //mark
    for(int i = 1 ; i <= n; i++) {
        int seg = 1<<i;
        for(int j = 1<<(i-1); j  < N; j += seg<<1){
                for(int k = 0; k < seg && j+k < N; k++)
                    Rotate[j+k]++;
        }
    }

    //rotate and calculate position
    int minx = 0,miny = 0;
    x[0] = y[0] = 0;
    for(int i = 1; i < N; i++){
        int &u = dir[i] , u2 = dir[i-1];
        u = (u + Rotate[i])%4;
        x[i] = x[i-1] + dx[u2] + mx[u] ;
        y[i] = y[i-1] + dy[u2] + my[u] ;
        minx = min(minx,x[i]);
        miny = min(miny,y[i]);
    }
    //normalize
    for(int i = 0; i < N; i++){
        x[i] -= minx;
        y[i] -= miny;
    }

    for(int i = 0; i < N; i++) r[i] = i;
    sort(r,r+N,cmp);

    int prex = 0,prey = -1;
    for(int i = 0; i < N; i++){
        int id = r[i];
        if(x[id] != prex) putchar('
'),prey = -1;
        for(int j = prey+1; j < y[id]; j++) putwchar(' ');
        putchar(decode[dir[id]]);
        prey = y[id]; prex = x[id];
    }
    printf("
^
");
}


int main()
{
   // freopen("out.txt","w",stdout);
    int n;
    while(scanf("%d",&n),n){
        solve(n);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4699728.html