蛇形矩陣題解

題目描述:

  輸入正數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;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章