题目描述:
输入正数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;
}
}
- 本次解题由陈丰同学讲授。