UVa 177 - Paper Folding

链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=113

 

题意:

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

 

分析:

 

 

 

如图所示,圆圈A,B表示展开时的旋转点,其余字母代表线段。
看图找规律。线段位置变化顺序是:左上 -> 右上 -> 右下 -> 左下 -> 左上
当以B为旋转点(第三次展开)时。B左边的第一条线段是一条横线(即e),
而且所有旋转点左边的第一条线段都是横线。
因为B的左边部分是由B的下边部分旋转得来,所以其余线段可根据上面的线段位置变化顺序得出:
因为c在d的右下方,所以e的下一条线段(即f)在e的左下方。
因为b在c的右下方,所以f的下一条线段(即g)在f的左下方。
因为a在b的左下方,所以g的下一条线段(即h)在g的左上方。
依照此规律就可以生成一条完整的曲线了。

 

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 const int dr[8] = {1, 0, 1, 0, 0, -1, 0, -1};
 5 const int dc[8] = {1, 1, -1, -1, -1, -1, 1, 1};
 6 const char dch[8+5] = "||||____";
 7 
 8 struct COORDINATE {
 9     int r, c; //行坐标,列坐标
10 } a[9999]; //生成的线段序列,可以看作一个栈
11 
12 char s[300][300]; //用一个二维数组保存图像
13 int p, sr, tr, sc, tc[300]; //栈顶指针,图像的开始行,结束行,开始列,每一行的结束列
14 
15 void init(){
16     memset(s, ' ', sizeof(s));
17     memset(tc, 0, sizeof(tc));
18     a[0] = (COORDINATE){150, 150};
19     a[1] = (COORDINATE){150, 151};
20     s[a[0].r][a[0].c] = '_';
21     s[a[1].r][a[1].c] = '|';
22     p = 2;  sr = a[0].r;  tr = a[1].r;  sc = a[0].c;  tc[tr] = a[1].c;
23 }
24 
25 void make(int r, int c, char ch){
26     a[p] = (COORDINATE){r, c};
27     s[a[p].r][a[p].c] = ch;
28     if(sr > r) sr = r;
29     if(tr < r) tr = r;
30     if(sc > c) sc = c;
31     if(tc[r] < c) tc[r] = c;
32     p++;
33 }
34 
35 void dfs(int d, int dep){
36     if(d > dep) return;
37     make(a[p-1].r - 1, a[p-1].c - 1, '_');
38     for(int i = p - 2; i > 0; i--){
39         COORDINATE R = a[i], L = a[i-1];
40         int d = (s[R.r][R.c] == '_') * 4 + (R.r == L.r) * 2 + (R.c > L.c); //判断下一条线段的位置
41         make(a[p-1].r + dr[d], a[p-1].c + dc[d], dch[d]);
42     }
43     dfs(d + 1, dep); //下一次展开
44 }
45 
46 int main(){
47     int n;
48     while(scanf("%d", &n) && n){
49         init();
50         dfs(2, n);
51         for(int r = sr; r <= tr; r++){
52             for(int c = sc; c <= tc[r]; c++) printf("%c", s[r][c]);
53             printf("\n");
54         }
55         printf("^\n");
56     }
57     return 0;
58 }

 

转载于:https://www.cnblogs.com/hkxy125/p/8331773.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值