題目描述:
輸入正數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;
}
}
- 本次解題由陳豐同學講授。