题目信息:题目链接
蛇形填数
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
在n*n方陈里填入1,2,...,n*n,要求填成蛇形。例如n=4时方陈为:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
-
输入
- 直接输入方陈的维数,即n的值。(n<=100) 输出
- 输出结果是蛇形方陈。 样例输入
-
3
样例输出
-
7 8 1 6 9 2 5 4 3
思路分析:
这是一道很经典的分治法题目,类似的题目像数字旋转方阵,都是这样的一个处理过程。
首先,介绍一下,什么叫做分治法.
分治法是一种解题策略,将问题划分成较小规模的子问题,再求解子问题,得到的子问题合并起来(具体问题具体的合并策略),合并的界即为原问题的解。
划分子问题要将子问题划分为不可在分的原子问题(照样由题目的信息划分);
求解子问题,这要根据具体的问题具体去求解,像排序问题是比较大小,最近对问题是求两点之间的距离。同样这样的求解子问题,不是只要求每一个原子问题就可以的了,在第一次划分的时候就要考虑到问题的解,可能出现在那些情况:划分的左边还是右边,或者是中间,像这样的,比较具有代表的就是最大字段和问题。
最后一步是合并子问题。
上面是一些粗略的介绍,关于分治法建议多做几道经典的题型,像归并排序,快速排序,最大字段和问题,数字旋转方阵,最近对问题等,掌握其方法更为重要!
分治法的解题步骤介绍了,接下来要讲解在这道题目中是如何运用的。
i表示行,j表示列。
首先第一步就是划分,如何划分呢?观察这个方阵发现,每一层中(这一个循环)数字是从右上角开始旋转,转了四下:从上到下(i++,j不变),从右到左(i不变,j--),从下到上(i--,j不变),从左到右(i不变,j++)。而在里面的每一层中,也是一样的规律。因此,我们以层作为代表来处理整个方阵。由刚才的旋转规分析,可以将层划分为四个并列的部分(并列的意思是处理完A之后,再处理B...而不是B在A中处理,这个说的好复杂的样子,看代码你就懂了~)
划分为四个部分之后,求解每一部分,从右上角开始,顺时针旋转,当走到起点的时候,一层结束,然后进入到下一层:i行加一,j列减一开始,继续这样的一个数字旋转,其中你的方阵规模不再是第一次的那个n了(这个方阵规模指的是你当前数字旋转的那一层),减小为n-2。例:图中最外层的规模为4.接下来的那一层是2(4-2)。
好了,现在你知道你的数字是如何划分的了,以及他的规律。现在最重要的是,也是分治法最关键的一部分,你程序的出口(大多数分治法采用的是递归的方法),这个题目,我们观察可以发现,当数字开始的下标i==j(n为奇数)或者i<j(n为偶数
)的时候,程序退出。
ok,思维上的讲解就到这里,接下来看看代码是如何实现的。(我觉得我讲得乱七八糟的,还是看代码来得直接,更容易懂。)
代码实现:
package com.BasicThree;
import java.util.Scanner;
/**
* Dragon
* 2017/4/28
*/
public class Num_33
{
static int[][] snake=new int[101][101];
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
int n=in.nextInt();
GetSnake(n,1,n,1);
PrintSnake(n);
}
private static void PrintSnake(int n)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
System.out.print(snake[i][j]+" ");
}
System.out.println();
}
}
//方阵的下标是从1开始的!
private static void GetSnake(int n, int startRow, int startCow, int number)
{
//程序出口
if(startCow<startRow)
return;
if(startCow==startRow)
{
snake[startRow][startCow]=number;
return;
}
int i=startRow;
for(int k=1;k<n;i++,k++)
{
snake[i][startCow]=number;
number++;
}
int j=startCow;
for(int k=1;k<n;j--,k++)
{
snake[i][j]=number;
number++;
}
for(int k=1;k<n;k++,i--)
{
snake[i][j]=number;
number++;
}
for(int k=1;k<n;k++,j++)
{
snake[i][j]=number;
number++;
}
GetSnake(n-2, startRow+1, startCow-1, number);
}
}