吐槽一下,官方给出的图我真的是看不出十字,更找不到任何规律.还有就是真的太久没刷题,思维就跟不上了,太菜了.
题目要求就不写了,直接上一张能看明白的图吧
这才叫十字啊(抠鼻)
题解1(递归解法)
这个大十字可以看成是一个个的红圈儿和中间的那个十字组成的,只要在一个二维数组中画出了最外层的红圈,就能用相同的方法,画出所有的红圈,再加上中间的十字,这个题就OK了,递归的过程就是在二维数组中从外向里画红圈.画一个红圈又分成了几步,上(第一,二,三行),下(倒数第一,二,三行),左(左边第一列),右(右边第一列)
代码
import java.util.Scanner;
public class PREV_2 {
static int count;//递归次数
static char[][] ch;//二维数组
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int num=5+4*n;//二维数组的总行数,总列数
count=n;
ch=new char[num][num];
for(int i=0;i<num;i++){
for(int j=0;j<num;j++){
ch[i][j]='.';
}
}
mid();
surrounded(0,num,0);
print();
}
//画外层的大十字
public static void surrounded(int head ,int num,int temp){//temp为当前递归次数,
if(temp>=count)return;//如果递归次数够了,就退出
//画第一行,倒数第一行
for(int i=head+2;i<num-2;i++){
ch[head][i]='$';
ch[num-1][i]='$';
}
//画第二行,倒数第二行
ch[head+1][head+2]='$';
ch[head+1][num-3]='$';
ch[num-2][head+2]='$';
ch[num-2][num-3]='$';
//画第三行,倒数第三行
int temp1=0;//用于循环时打印'$'
for(int i=head;i<head+3;i++){
//第三行
ch[head+2][i]='$';//左边
ch[head+2][num-1-temp1]='$';//右边
//倒数第三行
ch[num-3][i]='$';//左边
ch[num-3][num-1-temp1]='$';//右边
temp1++;
}
//画左右两边
for(int i=head+2;i<num-2;i++){
ch[i][head]='$';//左边
ch[i][num-1]='$';//右边
}
temp++;
surrounded(head+2,num-2,temp);//递归调用
}
//画中间的十字
public static void mid(){
int midline=ch.length/2;
int j=count*2;
for(int i=0;i<5;i++){
ch[midline][j+i]='$';
ch[j+i][midline]='$';
}
}//打印图形
public static void print(){
for(int i=0;i<ch.length;i++){
for(int j=0;j<ch.length;j++){
System.out.print(ch[i][j]);
}
System.out.println();
}
}
}
题解2(分治解法)
那个大十字可以看出是由4部分组成,左上,右上,左下,右下,而且四部分是相同的,只是存在镜像关系,只要能得到任意一部分,就能得到4部分,以输入1的十字图,左上部分为例,先确定四个点(四个白格),再确定每一层,具体见代码
代码
import java.util.Scanner;
public class PREV_2{
public static void main(String args[]){
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int num=4*n+5;//需要打印的总行数,总列数
char [][]c=new char[num][num];//最终的二维数组
int [][]c1=new int[(num/2)+1][(num/2)+1];//左上部分的数字数组便于判断
char [][]m=new char[(num/2)+1][(num/2)+1];//左上部分的二维数组
for(int i=0;i<num;i++){
for(int j=0;j<num;j++){
c[i][j]='.';//设置初始值
}
}
for(int i=0;i<c1.length;i++){
for(int j=0;j<c1.length;j++){
c1[i][j]=30;//设置初始值为30,因为该题最多有29层,也可以是任意一个数,最好与本题无关的一个数
}
}
c1[0][0]=0;//将4个点设置为0,便于区分
c1[0][1]=0;
c1[1][0]=0;
c1[1][1]=0;
for(int k=0;k<n*2;k++){//大的循环次数
for(int i=0;i<c1.length;i++){
for(int j=0;j<c1.length;j++){
if(c1[i][j]==30){//即就是从未扫描到的,因为扫描到了的会被重新赋值
if((i==0||j==0)||c1[i-1][j-1]==k){//看图, 如果在边缘,或者斜上角是上一层赋的值,那么这个应该赋值
c1[i][j]=k+1;//为什么每一轮的值要不一样,如果一样的话,会影响到下一层判断
}
}
}
}
}
//数字数组转成'.'$'数组
for(int i=0;i<c1.length;i++){
for(int j=0;j<c1.length;j++){
if(c1[i][j]%2==0){//偶数对应的是'.',奇数对应的是'$'
m[i][j]='.';
}else{
m[i][j]='$';
}
}
}
//组成总二维数组,需要找到每一块和左上数组的数学关系.
for(int i=0;i<5+(n-1)*2;i++){
for(int j=0;j<5+(n-1)*2;j++){
c[i][j]=m[i][j];//左上
c[i][j+5+(n-1)*2-1]=m[i][5+(n-1)*2-1-j];//右上
c[5+(n-1)*2-1+i][j]=m[5+(n-1)*2-1-i][j];//左下
c[5+(n-1)*2-1+i][5+(n-1)*2-1+j]=m[5+(n-1)*2-1-i][5+(n-1)*2-1-j];//右下
}
}
for(int i=0;i<c.length;i++){
for(int j=0;j<c.length;j++){
System.out.print(c[i][j]);
}
System.out.println();
}
}
}
总结:还是得每天练练题,保持手感,不然思维真的会退化.对了,打个广告,这是我的个人网站哦,点我点我有想练练手的小伙伴,可以评论,我告诉你github上的链接哦.