[Java]伯俊2447号[星を撮る-10]Java


白駿2447号です.
https://www.acmicpc.net/problem/2447

質問する


再帰的なパターンで星を撮りましょう.Nは3の累加二乗(3,9,27.)である.表示、大きさNのパターンはN×n正方形形状.
大きさ3のパターンは真ん中にスペースがあり、真ん中のすべての格子を除いて星のパターンがあります.
***
* *
***
nが3より大きい場合、nサイズのパターンはスペースで塗りつぶされます(N/3).×(N/3)N/3の大きさのパターンで囲まれた正方形.例えば、サイズ27のパターンは、サンプル出力1と同じである.

入力


1行目はNです.Nは3の三次方です.すなわち、ある整数kに対して、N=3 kであり、このとき1≦k<8である.

しゅつりょく


1行目からN行目まで星を出力します.

入力例

27

サンプル出力

***************************
* ** ** ** ** ** ** ** ** *
***************************
***   ******   ******   ***
* *   * ** *   * ** *   * *
***   ******   ******   ***
***************************
* ** ** ** ** ** ** ** ** *
***************************
*********         *********
* ** ** *         * ** ** *
*********         *********
***   ***         ***   ***
* *   * *         * *   * *
***   ***         ***   ***
*********         *********
* ** ** *         * ** ** *
*********         *********
***************************
* ** ** ** ** ** ** ** ** *
***************************
***   ******   ******   ***
* *   * ** *   * ** *   * *
***   ******   ******   ***
***************************
* ** ** ** ** ** ** ** ** *
***************************

考える


正直、この問題は個人的に難しいと思います.最近ダイナミックプランニングを勉強しています
復帰した分割征服にも勉強が必要だと思い、問題を解決しました.
どのように設計すればいいのか分からず、1時間ほど悩んだあげく、他の人の解答を参考にした.
コメント
この問題を解決して星を出力する場合は、StringBuilderとBufferedWriterの2つの選択から1つを選択して出力する必要があります.
しかし、私は以前StringBuilderだけで印刷していました.
BufferedWriterを使うのは初めてで、
結果はStringBuilderよりずっと良くて驚きました.

アクション


  • 		int size = N / 3;
    		int count = 0;
    		for(int i=x; i<x + N; i+=size) {
    			for(int j=y; j<y + N; j+=size) {
    				count ++;
    
    				if(count == 5) {
    					makeStar(i, j, size, true);
    				}
    				else {
    					makeStar(i, j, size, false);
    				}
    			}
    		}
    配列の作成や初期化などは省略し、「*」を配列に入れることから説明します.
    先に始めると、上のコードから実行されます.
    私たちが星を撮る過程は小さなブロックから考えるべきだ.Nが27の場合、9の矩形は先に完成しなければならず、9の矩形は完成する前に、3の矩形は先に完成しなければならない.
    また,3の矩形を生成するためには,一つの星を出力する必要がある.N->27->9->3->1の順序で、小方体からサイズ自体の処理を開始します.
    また、if(count == 5) {の条件はNが3の場合、星は5番目に共通の空白が現れる.
    したがって、countの変数は、5番目の位置でブランクを処理するために、繰り返しごとに1回増加する.
    すなわち、目標は、サイズNのxおよびyに適合する座標値を作成し、そのサイズに従ってループおよび繰返しを行うことである.

  • 		// 공백칸일 경우
    		if(blank) {
    			for(int i=x; i<x + N; i++) {
    				for(int j=y; j<y + N; j++) {
    					arr[i][j] = ' ';
    				}
    			}
    			return;
    		}
    
    		if(N == 1) {
    			arr[x][y] = '*';
    			return;
    		}
    
    再帰関数がループ全体で実行されると、Nすなわち大きさが1の場合、星を配列に入れる.
    あるいは、count == 5の条件において、blankがtrueである場合
    サイズに応じてスペースを出力します.

    コード#コード#


    Buffered Writerの使用

    import java.io.*;
    
    public class Main {
    		static char arr[][];
    
    	public static void main(String[] args) throws Exception {
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    
    		int N = Integer.parseInt(br.readLine());
    
    		arr = new char[N][N];
    
    		makeStar(0, 0, N, false);
    
    		// 출력 
    		for(int i=0; i<N; i++) {
    			bw.write(arr[i]);
    			bw.write('\n');
    		}
    
    		bw.flush();
    		bw.close();
    
    	} // End of main
    
    	static void makeStar(int x, int y, int N, boolean blank) {
    
    		// 공백칸일 경우
    		if(blank) {
    			for(int i=x; i<x + N; i++) {
    				for(int j=y; j<y + N; j++) {
    					arr[i][j] = ' ';
    				}
    			}
    			return;
    		}
    
    		if(N == 1) {
    			arr[x][y] = '*';
    			return;
    		}
    
    		int size = N / 3;
    		int count = 0;
    		for(int i=x; i<x + N; i+=size) {
    			for(int j=y; j<y + N; j+=size) {
    				count ++;
    
    				if(count == 5) {
    					makeStar(i, j, size, true);
    				}
    				else {
    					makeStar(i, j, size, false);
    				}
    			}
    		}
    		
    
    	}// End of makeStar
    } // End of class

    StringBuilderの使用

    import java.io.*;
    
    public class Main {
    	static char arr[][];
    
    	public static void main(String[] args) throws Exception {
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    
    		int N = Integer.parseInt(br.readLine());
    
    		//27은 3의 세제곱
    		arr = new char[N][N];
    
    		makeStar(0, 0, N, false);
    
    		// arr 배열 출력.
    		StringBuilder sb = new StringBuilder();
    		for(int i=0; i<N; i++) {
    			for(int j=0; j<N; j++) {
    				sb.append(arr[i][j]);
    			}
    			sb.append('\n');
    		}
    		System.out.println(sb);
    
    	} // End of main
    
    	static void makeStar(int x, int y, int N, boolean blank) {
    
    
    		// 공백칸일 경우
    		if(blank) {
    			for(int i=x; i<x + N; i++) {
    				for(int j=y; j<y + N; j++) {
    					arr[i][j] = ' ';
    				}
    			}
    			return;
    		}
    
    		// 더이상 쪼갤 수 없는 블록일 때
    		// 27 -> 9 -> 3 -> 1로 와서 N이 1일때
    		if(N == 1) {
    			arr[x][y] = '*';
    			return;
    		}
    
    		int size = N / 3;
    		int count = 0;
    		for(int i=x; i<x + N; i+=size) {
    			for(int j=y; j<y + N; j+=size) {
    				count ++;
    
    				if(count == 5) {
    					makeStar(i, j, size, true);
    				}
    				else {
    					makeStar(i, j, size, false);
    				}
    			}
    		}
    
    
    	}// End of makeStar
    } // End of class