螺旋矩阵

1.螺旋矩阵--从内向外旋转

   73   74   75   76   77   78   79   80  81
   72   43   44   45   46   47   48   49   50
   71   42   21   22   23   24   25   26   51
   70   41   20    7     8      9   10   27   52
   69   40   19    6  
  1     2    11   28   53
   68   39   18    5     4     3    12   29   54
   67   38   17   16   15   14   13   30   55
   66   37   36   35   34   33   32   31   56
   65   64   63   62   61   60   59   58   57


       看清以上数字排列的规律,设1点的坐标是(0,0),x方向向右为正,y方向向下为正。例如:7的坐标为(-1,-1),2的坐标为(1,0),3的坐标为(1,1)。编程实现输入任意一点坐标(x,y),输出所对应的数字;或输入任意数字,输出该数字的坐标。


解析:规律能看出来,问题就在于如何利用它。很明显这个队列是顺时针螺旋向外扩展的,我们可以把它看成一层一层往外延伸。第 0 层规定为中间的那个 1,第 1 层为 2 到 9,第 2 层为 10 到 25,注意到 1、9、25、……不就是平方数吗?而且是连续奇数(1、3、5、……)的平方数。这些数还跟层数相关,推算一下就可以知道第 t 层之内一共有 (2t-1)^2 个数,因而第 t 层会从 [(2t-1)^2] + 1 开始继续往外螺旋。给定坐标 (x,y),如何知道该点处于第几层?层数 t = max(|x|,|y|)。

  知道了层数,接下来就好办多了,这时我们就知道所求的那点一定在第 t 层这个圈上,顺着往下数就是了。要注意的就是螺旋队列数值增长方向和坐标轴正方向并不一定相同。我们可以分成四种情况——上、下、左、右——或者——东、南、西、北,分别处于四条边上来分析。

  东|右:x == t,队列增长方向和 y 轴一致,正东方向(y = 0)数值为 (2t-1)^2 + t,所以 v = (2t-1)^2 + t + y

  南|下:y == t,队列增长方向和 x 轴相反,正南方向(x = 0)数值为 (2t-1)^2 + 3t,所以 v = (2t-1)^2 + 3t - x

  西|左:x == -t,队列增长方向和 y 轴相反,正西方向(y = 0)数值为 (2t-1)^2 + 5t,所以 v = (2t-1)^2 + 5t - y

  北|上:y == -t,队列增长方向和 x 轴一致,正北方向(x = 0)数值为 (2t-1)^2 + 7t,所以 v = (2t-1)^2 + 7t + x

  其实还有一点很重要,不然会有问题。其它三条边都还好,但是在东边(右边)那条线上,队列增加不完全符合公式!注意到东北角(右上角)是本层的最后一个数,再往下却是本层的第一个数,那当然不满足东线公式啊。所以我们把东线的判断放在最后(其实只需要放在北线之后就可以),这样一来,东北角那点始终会被认为是北线上的点。


输入任意一点坐标(x,y),输出所对应的数字:

#include"stdafx.h"
#include<iostream>

using namespace std;

#define max(a,b) ((a)>(b)?(a):(b))
#define abs(a) ((a)>0?(a):-(a))

int spiralQueue(int x, int y){
	int t = max(abs(x),abs(y));
	int s = (2 * t - 1) * (2 * t - 1);
	int v;

	if(y == -t){
		v = s + 7 * t + x;
	}else if(y == t){
		v = s + 3 * t - x;
	}else if(x == -t){
		v = s + 5 * t - y;
	}else{
		v = s + t + y;
	}
	return v;
}

int main(){
	int x,y;
	for(y = -2;y <= 2; y++){
		for(x = -2; x <= 2; x++){
			cout<<spiralQueue(x,y)<<" ";
		}
		cout<<endl;
	}
}

输入任意数字,输出该数字的坐标:

#include"stdafx.h"
#include<iostream>

using namespace std;

void spiralQueue2(int v){
	int x,y;
	//首先确定所在层数
	int t = 0;//层数
	int s = 1;
	while(v > s){
		t++;
		s = (2 * t + 1) * (2 * t +1);
	}
	//确定在哪一条边
	int a = v - ((2 * t - 1) * (2 * t -1) + 1);//与第一个数字的差值
	if(a <= 2*t-1){//右边
		x = t;
		y = v - ((2 * t - 1) * (2 * t -1) + t);
	}else if(a <= 4*t-1){//下边
		x = -(v - ((2 * t - 1) * (2 * t -1) + 3*t));
		y = t;
	}else if(a <= 6*t-1){//左边
		x = -t;
		y = -(v - ((2 * t - 1) * (2 * t -1) + 5*t));
	}else{//上边
		x = v - ((2 * t - 1) * (2 * t -1) + 7*t);
		y = -t;
	}
	cout<<"("<<x<<","<<y<<")"<<endl;
}

int main(){
	int v;
	while((cin>>v) && (v>0)){
		spiralQueue2(v);
	}
}

2.螺旋矩阵--从外向内旋转

对m * n 矩阵,最先访问最外层的m * n的矩形上的元素,接着再访问里面一层的 (m - 2) * (n - 2) 矩形上的元素…… 最后可能会剩下一些元素,组成一个点或一条线(见图1)。

对第i个矩形(i=0, 1, 2 …),4个顶点的坐标为:

(i, i) ----------------------------------------- (i, n–1-i)

|                                                    |

|                                                    |

|                                                    |

(m-1-i, i) ----------------------------------------- (m-1-i, n-1-i) 

要访问该矩形上的所有元素,只须用4个for循环,每个循环访问一个点和一边条边上的元素即可(见图1)。另外,要注意对最终可能剩下的1 * k 或 k * 1矩阵再做个特殊处理。


按顺时针方向构建一个m * n的螺旋矩阵

矩阵为方阵:

#include"stdafx.h"
#include<iostream>

using namespace std;

void spiralQueue(int n){
	//分配空间
	int ** a = (int**)malloc(sizeof(int*)*n);
	if(a == NULL){
		return;
	}
	int j;
	for(j = 0; j < n; j++){
		a[j] = (int*)malloc(sizeof(int)*n);
		if(a[j] == NULL){
			j--;
			while(j >= 0){
				free(a[j]);
			}
			free(a);
		}
	}
	int m = 1;
	int i;
	//分层填充
	for(i = 0; i < n/2; i++){
		int k = n - i - 1;
		//上边
		for(j=i;j < k; j++){
			a[i][j] = m++;
		}
		//右边
		for(j=i;j < k; j++){
			a[j][k] = m++;
		}
		//下边
		for(j=k;j >i; j--){
			a[k][j] = m++;
		}
		//左边
		for(j=k;j >i; j--){
			a[j][i] = m++;
		}
	}
	if(n % 2 == 1){
		a[n/2][n/2] = m;
	}

	for(i = 0; i < n; i++){
		for(j = 0; j < n; j++){
			cout<<a[i][j]<<" ";
		}
		cout<<endl;
	}
}

int main(){
	int v;
	while((cin>>v) && (v>0)){
		spiralQueue(v);
	}
}
矩阵为m*n矩阵:

#include"stdafx.h"
#include<iostream>

using namespace std;

void spiralQueue(int m,int n){
	//分配空间
	int ** a = (int**)malloc(sizeof(int*)*m);
	if(a == NULL){
		return;
	}
	int j;
	for(j = 0; j < m; j++){
		a[j] = (int*)malloc(sizeof(int)*n);
		if(a[j] == NULL){
			j--;
			while(j >= 0){
				free(a[j]);
			}
			free(a);
		}
	}
	int v = 1;
	int count = m < n ? m : n;

	int i;
	//分层填充
	for(i = 0; i < count/2; i++){
		int row = m - i - 1;
		int col = n - i - 1;
		//上边
		for(j=i;j < col; j++){
			a[i][j] = v++;
		}
		//右边
		for(j=i;j < row; j++){
			a[j][col] = v++;
		}
		//下边
		for(j=col;j >i; j--){
			a[row][j] = v++;
		}
		//左边
		for(j=row;j >i; j--){
			a[j][i] = v++;
		}
	}
	if(count % 2 == 1){
		if(count == m){
			int row = m/2;
			int col = n - count/2;
			for(int k = count/2; k < col; k++){
				a[row][k] = v++;
			}
		}else{
			int row = m - count/2;
			int col = n/2;
			for(int k = count/2; k < row; k++){
				a[k][col] = v++;
			}
		}
	}

	for(i = 0; i < m; i++){
		for(j = 0; j < n; j++){
			cout<<a[i][j]<<" ";
		}
		cout<<endl;
	}
}

int main(){
	int m,n;
	while((cin>>m>>n) && (m>0) && (n>0)){
		spiralQueue(m,n);
	}
}



在不构造螺旋矩阵的情况下,给定坐标ij值求其对应的值f(i, j)





  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值