题目描述:
给定一个自然数n,打印1-n之间所有的数,要求:按螺旋形状顺时针打印。
由内而外的打印
分析
最简单且直观的方法就是k * k的二维数组存储数字,先将数字按照要求填入数组,然后输出整个数组即可
分配数组
对于n个数而言,令k = Ceil(sqrt(n)), 则分配k*k的二维数组即可。比如n = 5时,分配3*3的数组即可。
如何填数
起始点
以左上角为起始点方向
用一个整数flag来标识方向
flag = 1 - 向右
flag = 2 - 向下
flag = 3 - 向左
flag = 4 - 向上边界判断
当到达边界的时候应该变换方向,即向右转,如何判断边界?我的方法是,将所有数组元素初始化为-1,则有如下两种情况
1.下标超出二维数组边界,则需转向(注意,转向之前下标需要退回一格)
2.下标未越界,但下一个位置的值不是-1,那么说明它被填充过,也需转向。填充
重复以下过程直到所有数据填充完毕。
- 从左至右填充数组,如遇右边界或者下一位置已经被填充过,则改变方向,转入步骤2
- 从上至下填充数组,如遇下边界或者下一位置已经被填充过,则改变方向,转入步骤3
- 从右至左填充数组,如遇左边界或者下一位置已经被填充过,则改变方向,转入步骤4
- 从下至上填充数组,如遇上边界或者下一位置已经被填充过,则改变方向,转入步骤1
代码实现:
#include <iostream>
#include <iomanip>
using namespace std;
//从外向内螺旋打印num
void SpiralPrint1(int num)
{
//计算二维数组的维数k
int k = ceil(sqrt(num)); //ceil()向上取整
//动态分配一个二维数组
int **a = new int*[k];
for (int i = 0; i < k; i++)
{
a[i] = new int[k];
}
//初始化动态分配的二维数组
for (int i = 0; i < k; i++)
for (int j = 0; j < k; j++)
a[i][j] = -1;
int i = 0, j = 0;
a[i][j] = 1;
// 用一个整数flag来标识方向
// flag -> 1 向右(j++) | flag -> 2 向下(i++) | flag -> 3 向左(j--) | flag -> 向上(i--)
int flag = 1;
int m = 1;
while (a[i][j] < num)
{
m++;
if (flag == 1)
{
j++;
if (j >= k || a[i][j] != -1)
{
j--;
flag = 2;
}
}
if (flag == 2)
{
i++;
if (i >= k || a[i][j] != -1)
{
i--;
flag = 3;
}
}
if (flag == 3)
{
j--;
if (j <= -1 || a[i][j] != -1)
{
j++;
flag = 4;
}
}
if (flag == 4)
{
i--;
if (a[i][j] != -1 || i <= -1)
{
i++;
flag = 1;
j++;
if (j >= k || a[i][j] != -1)
{
j--;
}
}
}
a[i][j] = m;
}
for (int i = 0; i < k; i++)
{
for (int j = 0; j < k; j++)
cout << right << setw(5) << a[i][j] << " ";
cout << endl;
}
}
int main()
{
SpiralPrint1(25);
system("pause");
return 0;
}
由内而外的打印
起始位置
由于是从内向外填充,所以起始位置不再是(0, 0),需要重新计算,而且还与二维数组的阶数k的奇偶性相关
1 当k为奇数时,起始位置为(k / 2, k / 2),如下:
2 当k为偶数时,起始位置为(k / 2 - 1, k / 2 - 1),如下:边界判断
与从外向内填充不同的是,边界判断中不会再出现下标越界的情况,只需判断当前位置是否填充过即可
方向转换
从内向外填充时,能转向时优先转向,不能转向时才继续向前填充,而从外向内填充则恰恰相反,无法继续向前填充时才转向
代码实现:
#include <iostream>
#include <iomanip>
using namespace std;
void SpiralPrint2(int num)
{
//计算二维数组的维数k
int k = ceil(sqrt(num));
//动态分配一个二维数组
int **a = new int*[k];
for (int i = 0; i < k; i++)
{
a[i] = new int[k];
}
//初始化动态分配的二维数组
for (int i = 0; i < k; i++)
for (int j = 0; j < k; j++)
a[i][j] = -1;
int i, j;
if (k % 2 == 0)
i = j = k / 2 - 1;
else
i = j = k / 2;
a[i][j] = 1;
int m = 1;
int flag = 1;
while (m < num)
{
m++;
if (flag == 1)
{
j++;
if (a[i][j] == -1)
{
a[i][j] = m;
flag = 2;
}
else
{
j--;
i--;
if (a[i][j] == -1)
{
a[i][j] = m;
flag = 1;
}
}
}
else if (flag == 2)
{
i++;
if (a[i][j] == -1)
{
a[i][j] = m;
flag = 3;
}
else
{
i--;
j++;
if (a[i][j] == -1)
{
a[i][j] = m;
flag = 2;
}
}
}
else if (flag == 3)
{
j--;
if (a[i][j] == -1)
{
a[i][j] = m;
flag = 4;
}
else
{
j++;
i++;
if (a[i][j] == -1)
{
a[i][j] = m;
flag = 3;
}
}
}
else if (flag == 4)
{
i--;
if (a[i][j] == -1)
{
a[i][j] = m;
flag = 1;
}
else
{
i++;
j--;
if (a[i][j] == -1)
{
a[i][j] = m;
flag = 4;
}
}
}
}
for (int i = 0; i < k; i++)
{
for (int j = 0; j < k; j++)
{
cout << right << setw(5) << a[i][j] << " ";
}
cout << endl;
}
}
int main()
{
SpiralPrint1(25);
system("pause");
return 0;
}
题目描述:
把一个个大小差一圈的框叠起来,使得从上往下看时,边框花色交错,这个工作现在要让计算机来完成
输入:
输入时一个个的三元组,分别是,外框尺寸n(n为满足0
输出:
输出叠在一起的框案,中心花色和外框花色字符从内层起交错相叠,多狂想叠时,最外框的角总是被打磨掉。叠框和叠框之间一行间隙
样例输入:
5 @ w
样例输出:
@ @ @
@ w w w @
@ w @ w @
@ w w w @
@ @ @
样例输入:
11 B A
样例输出:
A A A A A A A A A
A B B B B B B B B B A
A B A A A A A A A B A
A B A B B B B B A B A
A B A B A A A B A B A
A B A B A B A B A B A
A B A B A A A B A B A
A B A B B B B B A B A
A B A A A A A A A B A
A B B B B B B B B B A
A A A A A A A A A
思想关键:按照由最内圈至最外圈的顺序来完成图形的排序。在完成每圈打印时,注意两个要点:首先需要确定最上角的坐标。我们将以这个坐标作为参照点来完成该圈的其他位置上的字符位置的确定
代码实现
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int n;
char a, b;
while (cin >> n >> a >> b)
{
//动态创建一个二维数组用于存储数据
char **output = new char*[n];
for (int i = 0; i < n; i++)
{
output[i] = new char[n];
}
int k = n / 2;
output[k][k] = a;
for (int i = 1; i <= n / 2; i++)
{
char c;
if (i % 2 == 0)
c = a;
else
c = b;
for (int j = 0; j < 2 * i + 1; j++)
{
output[k - i][k - i + j] = c; //上面一行的字符确定
output[k - i + j][k - i] = c; //左边一列的字符确定
output[k + i - j][k + i] = c; //右边一列的字符确定
output[k + i][k + i - j] = c; //下边一行的字符确定
}
}
if (n != 1)
{
output[0][0] = ' ';
output[n - 1][0] = ' ';
output[0][n - 1] = ' ';
output[n - 1][n - 1] = ' ';
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
cout << setw(3) << output[i][j] << " ";
cout << endl;
}
}
system("pause");
return 0;
}
本文参考:
http://www.cnblogs.com/graphics/archive/2010/06/05/1739658.html