编程能力提高------蛇形填数(方块填数+三角形填数) .
2016-06-05 11:15
288 查看
回忆曾经:
考研复试上机做题时,遇到过一次这个蛇形填数问题,当时不会做;后来又遇到一个蛇形填充(基于三角形),也不会做;这让我下定决心,一定要找到这两个问题的解,哪怕是抄别人的代码。后来才知道,这种问题,是学习ACM的入门问题。
问题一:描述
以下内容参考《算法竞赛入门经典(第2版)刘汝佳》
在n*n方阵里填入1,2,„,n*n,要求填成蛇形。例如n=4时方阵为
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
上面的方阵中,多余的空格只是为了便于观察规律,不必严格输出。n≤8。
问题分析:
字符的特殊图形输出问题,我们暂时可以分为2类。
第一类是有一定对称性的几何图形,比如说打印倒三角形或者菱形等。这种题目一般思路就是找出图形的特点(对称性等)与循环变量(行号,列号)之间的关系。我们可以假设行用i表示,列用j表示。我们的目的就是找出i,j与图形之间的对应关系。按图形形状的不同,i和j之间的复杂性不同。但是都可以看做是在寻找一种或多种"静态关系"。
第二类是有一定规律性的图形,比如蛇形填数,走棋盘等。这种题目的一般思路就是找出题目中对图形的限制条件(不能出界,按照一定规则填充等)。我们首先要通过观察理解用到的“规则”,然后用各种循环和if语句将这些"规则"变成程序语句。同样,根据"规则"不同,复杂性也不同。但是都可以看做是在寻找一种或多种i和j之间的"动态关系"。
通过观察,我们可以看出规则:在规定的方阵n*n里,在不越界及不走重复位置的前提下,填充元素遵循右下左上的规定.即向右走到顶后向下走到顶,再向左走到顶,向上走到顶。
类比数学中的矩阵,可以用一个二维数组来存储题目中的方阵。只要声明一个“int a[maxn][maxn]”,就可以获得一个大小为maxn*maxn的方阵,在声明时,二维的大小不必相同,因此也可以声明int a[30][50]这样的数组。
从1开始依次填写。设“笔”的坐标为(x,y),则一开始x=0,y=n-1,即第0行,第n-1列。“笔”的移动轨迹是:下,下,下,左,左,左,上,上,上,右,右,下,下,左,上。总之,先是下,到不能填为止,然后是左,接着是上,最后是右。“不能填”是指再走就出界(例如4→5),或者再走就要走到以前填过的格子(例如12→13)。如果把所有格子初始化为0,就能很方便地加以判断。在这里我们就要提到在很多时候都要用到的判断方法"预判".即提前一格判断下一格是否越界,如果下一格越界就不再移动。
4条while语句有些难懂,其实是有原则的。先判断,再行走,而不是走一步后发现越界再退回来。这样则需要进行“预判”,即是否越界,以及如果继续往下走会不会到达一个已经填过的格子。越界只需判断x+1<n,因为y的值并没有修改;下一个格子是(x+1,y),因此需要判断a[x+1][y]==0,简写成 “!a[x+1][y] ”。
问题二:描述
输入
第一行有一个N,表示N组测试数据
接下来每组数据包括一个数字X,表示三角形的边长,0< X <1000
输出
输出填好之后的图
样例输入
样例输出
考研复试上机做题时,遇到过一次这个蛇形填数问题,当时不会做;后来又遇到一个蛇形填充(基于三角形),也不会做;这让我下定决心,一定要找到这两个问题的解,哪怕是抄别人的代码。后来才知道,这种问题,是学习ACM的入门问题。
蛇形填数(一)蛇形矩阵
问题一:描述以下内容参考《算法竞赛入门经典(第2版)刘汝佳》
在n*n方阵里填入1,2,„,n*n,要求填成蛇形。例如n=4时方阵为
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
上面的方阵中,多余的空格只是为了便于观察规律,不必严格输出。n≤8。
问题分析:
字符的特殊图形输出问题,我们暂时可以分为2类。
第一类是有一定对称性的几何图形,比如说打印倒三角形或者菱形等。这种题目一般思路就是找出图形的特点(对称性等)与循环变量(行号,列号)之间的关系。我们可以假设行用i表示,列用j表示。我们的目的就是找出i,j与图形之间的对应关系。按图形形状的不同,i和j之间的复杂性不同。但是都可以看做是在寻找一种或多种"静态关系"。
第二类是有一定规律性的图形,比如蛇形填数,走棋盘等。这种题目的一般思路就是找出题目中对图形的限制条件(不能出界,按照一定规则填充等)。我们首先要通过观察理解用到的“规则”,然后用各种循环和if语句将这些"规则"变成程序语句。同样,根据"规则"不同,复杂性也不同。但是都可以看做是在寻找一种或多种i和j之间的"动态关系"。
通过观察,我们可以看出规则:在规定的方阵n*n里,在不越界及不走重复位置的前提下,填充元素遵循右下左上的规定.即向右走到顶后向下走到顶,再向左走到顶,向上走到顶。
类比数学中的矩阵,可以用一个二维数组来存储题目中的方阵。只要声明一个“int a[maxn][maxn]”,就可以获得一个大小为maxn*maxn的方阵,在声明时,二维的大小不必相同,因此也可以声明int a[30][50]这样的数组。
从1开始依次填写。设“笔”的坐标为(x,y),则一开始x=0,y=n-1,即第0行,第n-1列。“笔”的移动轨迹是:下,下,下,左,左,左,上,上,上,右,右,下,下,左,上。总之,先是下,到不能填为止,然后是左,接着是上,最后是右。“不能填”是指再走就出界(例如4→5),或者再走就要走到以前填过的格子(例如12→13)。如果把所有格子初始化为0,就能很方便地加以判断。在这里我们就要提到在很多时候都要用到的判断方法"预判".即提前一格判断下一格是否越界,如果下一格越界就不再移动。
#include <stdio.h> #include <string.h> #define MAXN 20 int a[MAXN][MAXN];//数组空间分配在main内外,有点区别 int main() { int n, x, y, count = 1; scanf("%d", &n); memset(a, 0, sizeof(a));//用于判断格子是否被填数,memset可以初始化二维数组。 x = 0; y = n-1; a[x][y] = 1; while(count < n*n) { while(x+1<n && !a[x+1][y]) a[++x][y] = ++count; //先判断越界,再判断格子是否填过数 while(y-1>=0 && !a[x][y-1]) a[x][--y] = ++count; while(x-1>=0 && !a[x-1][y]) a[--x][y] = ++count; while(y+1<n && !a[x][y+1]) a[x][++y] = ++count; } for(x = 0; x < n; x++) { for(y = 0; y < n; y++) printf("%3d", a[x][y]); printf("\n"); } system("PAUSE"); return 0; }
4条while语句有些难懂,其实是有原则的。先判断,再行走,而不是走一步后发现越界再退回来。这样则需要进行“预判”,即是否越界,以及如果继续往下走会不会到达一个已经填过的格子。越界只需判断x+1<n,因为y的值并没有修改;下一个格子是(x+1,y),因此需要判断a[x+1][y]==0,简写成 “!a[x+1][y] ”。
蛇形填数(二)蛇形三角
问题二:描述1 2 3 4 5 12 13 14 6 11 15 7 10 8 9跟蛇形填数一样,只是填数要求按照三角形填。
输入
第一行有一个N,表示N组测试数据
接下来每组数据包括一个数字X,表示三角形的边长,0< X <1000
输出
输出填好之后的图
样例输入
2 5 4
样例输出
1 2 3 4 5 12 13 14 6 11 15 7 10 8 9 1 2 3 4 9 10 5 8 6 7
#include <iostream> #include <string.h> using namespace std; const int MAXN = 100; int data[MAXN][MAXN]; int main() { int n,length; cin>>n; while(n--) { memset(data,0,sizeof(data)); cin>>length; int x=0,y=0,cnt=1; data[x][y]=cnt; while(cnt<((length+1)*length)/2) { while ((y+1<length-x) && !data[x][y+1]) <span style="white-space:pre"> </span>data[x][++y]=++cnt; while ((x+1<length) && (y-1)>-1 &&!data[1+x][y-1] ) <span style="white-space:pre"> </span>data[++x][--y]=++cnt; while (x-1>-1 && (!data[x-1][y])) <span style="white-space:pre"> </span>data[--x][y]=++cnt; } for (int i=0;i< length ;i++) { for (int j=0;j<length-i;++j) { cout<<data[i][j]<<" "; } cout<<endl; } cout<<endl; } return 0; }
相关文章推荐
- Java中HashMap底层实现原理(JDK1.8)源码分析
- java - 观察者模式
- python2.7 倒计时
- JAVA反射机制
- 机器视觉开源代码集合-2
- C++第7次实验
- 机器视觉开源代码集合-1
- 非系统消息的使用方法及SendMessage()和PostMessage()的区别
- OpenJDK1.8.0 源码解析————HashMap的实现(一)
- 异常处理
- PHP学习笔记之面向对象(上)
- JAVA_OA(五):SpringMVC接受传入页面的参数值
- C#—实验10.4
- struts2的Action从页面获取传递的参数的三种方法
- 深度理解spring的IOC
- C++,笔试面试,使用C++编程,实现万年历
- C/C++,笔试面试,多种方法求100以内的所有素数
- 使用C语言编写程序,求解有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个序列的前20项
- worldwind java对TMS服务(腾讯)的支持
- C语言头文件的写作方法和说明