nyoj 蛇形填数 问题

题目如下:

描述在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的值。(n<=100)
输出
输出结果是蛇形方陈。
样例输入
3
样例输出
7 8 1
6 9 2
5 4 3


PS:此题虽为算法入门题,但也耗费了我大半天的时间,说明我的水平还是有待提高!(哭)

分析:

在解决本题的过程中,我主要思考过两种方法:

1.直接暴力解决(虽然我的解法也挺暴力的):但是过于问题在于,循环不好写,而且适用范围不大。能轻而易举的写出每一个n的外圈数,但是涉及到内圈填数时并不好执行。

例如你很容易写出n=3,n=4甚至n=5的情形,但要适用范围广必须得要有相应变量的变化和循环。

2.找到各位置数与 n 之间的规律,比如我找到的,[0][0]=n+2*(n-1),[1][1]=[0][n-1]+3n-5并以此作为出发点来填数。但是结果也并不能如愿。

主要原因:随着n的变化,之前所总结出来的规律可能不适用,因为这个矩阵总是在变化的。---(也可能是我数学水平太差,总结不出来吧....)

***************************************************************************************************************************

后来我的思路是这样:


按照蛇形填数的要求,重新理了一遍排列思路。并带入程序语言进去进行推理。

后来我发现这个填数实质上是可以不断切割成若干小的蛇形填数,我想象成从外往内填入数字。

所以,就可以将一个大的填数过程分解成无数个小的,然后对他们进行循环。

#include<iostream>
using namespace std;
int main()
{
	int n = 0;
	cin >> n;//输入的n
	int num[100][100];
	int k = 0;//循环中进行缩小圈的大小所用变量,用来将表左边进行缩小
	int i = 0;//表示纵坐标
	int j = 0;//表示横坐标
	int cnt = 0;//往表中填入的数
	int scale = n * n;//作为while和if执行的判断语句
	int N = n;//n在循环中会变化,N用来保存原始的n。n自减将右边进行缩小
	while (cnt != (scale)) {
		if (cnt !=(scale)) {
			for (i = k; i < n; i++) {
				j = n - 1;
				++cnt;
				num[i][j] = cnt;
			}//总是先填最后列
			--j;
			--i;
		}
		if (cnt != (scale)) {
			for (j; j >= k; j--) {
				++cnt;
				num[i][j] = cnt;
			}//第二次填最下面一行
			++j;
			--i;
		}
		if (cnt !=(scale)) {
			for (i; i >= k; i--) {
				++cnt;
				num[i][j] = cnt;
			}//最左边一列
			++i;
			++j;
		}
		if (cnt != (scale)) {
			for (j; j < n-1; j++) {
				++cnt;
				num[i][j] = cnt;
			}//最上边一行
		}
		--n;
		++k;//没填完一个圈,就缩小一次
	}
	//cout << 1 << endl;
	i = 0;
	j = 0;
	for (i; i < N; i++) {
		j = 0;
		for (j; j < N; j++) {
			cout << num[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

这就是完整的代码。

特别值得注意的是每个行,列填写中的i与j是否越界的问题,要进行检查,并加以处理。

检查的方法很简单,加一个cout<<i<<endl<<j<<endl;就可以再测试时检查每一个i,j是否越界。

也可以用此方法检查cnt,n和k;

最后一点就是while和if的判断问题。想的简单一点,找到蛇形填数结束的规律,总是填到数为n*n时结束,so就将其当做判断条件。当然也有其他的判断条件,这里就不再赘述。

***************************************************************************************************************************

总结:

按照填数规律填数;

一圈填完后缩小表,采用n自减缩小右侧,k自加缩小左侧的方法;

注意i,j,数组不要越界;

判断条件:填入数!=n*n;


猜你喜欢

转载自blog.csdn.net/xuchen1230/article/details/79605178