蛇形矩阵题解

2 篇文章 0 订阅
题目描述:

  输入正数n,按照下列格式进行在屏幕上打印出n到1。

输入格式:

  整数n(n<50)。

输出格式:

  输出蛇形排列的n。

样例输入:

10

样例输出:

10 9 5 4
8 6 3
7 2
1

解法一:

  根据输出,我们可以将输出方向(模式)分为四种方向:向右、左下、向下和右上。然后根据这四种方式初始化二维数组即可。

#include<iostream>
using namespace std;
int main()
{
	int matrix[10][10] = {0};
	// 方向相当于坐标变换
	// (0,1) 相当于行不变,列+1,即向右一步
	// (1,-1) 相当于行+1,列-1,即左下一步
	// (1,0) 相当于行+1,列不变,即向下一步
	// (-1,1) 相当于行-1,列+1,即右上一步
	int forward[4][2] = {0,1,1,-1,1,0,-1,1};
	int i = 0 , j = 0;
	// step记录当前输出方向(模式)
	int n, step = 0;
	cin>>n;
	matrix[0][0] = n;
	n--;
	while(n != 0)
	{
		if(step % 4 == 0)
		{
			// 向右
			i += forward[0][0];
			j += forward[0][1];
			// (i,j) = (0,1)
			matrix[i][j] = n;
			n--;
		} 
		else if(step % 4 == 1)
		{
			// 左下
			while(j > 0)
			{
				i += forward[1][0];
				j += forward[1][1];
				// (i,j) = (0 + 1 , 1 + (-1)) = (1,0)
				matrix[i][j] = n;
				n--;
				if(n == 0)
				{
					break;
				}
			}
		}
		else if(step % 4 == 2)
		{
			// 向下
			i += forward[2][0];
			j += forward[2][1];
			// (i,j) = (1 + 1,0 + 0) = (2,0)
			matrix[i][j] = n;
			n--;

		}
		else
		{
			while( i > 0)
			{
				// 右上
				i += forward[3][0];
				j += forward[3][1];
				matrix[i][j] = n;
				n--;
				if(n == 0)
				{
					break;
				}
			}

		}
		step ++ ;
	}
	// 输出
	for(i = 0 ; i < 10 && matrix[i][j]!=0; i ++)
	{
		for(j = 0 ; j < 10 && matrix[i][j] != 0; j ++)
		{
			if(matrix[i][j] != 0)
			{
				cout<<matrix[i][j]<<" ";
			}
			if(matrix[i][j] == 1)
			{
				break;
			}
		}
		j = 0;
		cout<<endl;
	}
}
解法二:

  找规律,推公式。将左下到右上(或右上到左下)看作是我们的标准方向,在每个标准方向上找到该方向的最大值,如题:第一个方向上最大为:10,第二个方向上最大为9,第三个方向上为7,以此类推…
  根据上述定义,我们可以找出以下规律:

  • 每个标准方向上,行列之和相等,且行列之和为:0,1,2,3,4…如:10所在的是0行0列,行列和为0;9 、8所在的是0行1列1行0列,行列和为1;7、6、5所在标准方向上的行列和为2,以此类推。
  • 当行列和为偶数时,该标准方向是向着右上的;当行列和为奇数时,该标准方向是向着左下
  • (最重要的一条规律)当行列和为偶数时,每个位置的值为:当前标准方向上的最大值减去当前列数;当行列和为奇数时,每个位置的值为:当前标准方向上的最大值减去当前行数。
#include<iostream>
using namespace std;
int main()
{
	int all;
	cin>>all;
	// 计算循环次数
	int time = (-1 + sqrt(double (1 + 8 * all))) / 2;
	for(int i=0;i<=time;i++)
	{
		for(int j=0;j<=time;j++)
		{
			// (i+j)&1 :判断行列和奇偶,奇数返回true,偶数返回false
			int ans=all - (i+j)*(i+j+1)/2-((i+j)&1?i:j);
			if(ans >0) 
				cout<<ans<<" ";
		}
		cout<<endl;
	}
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值