알고리즘/📌백준
색종이 만들기
IMSfromSeoul
2021. 12. 16. 03:05
문제
- 문제 유형 : 분할정복
색종이를 절반씩 나누어서, 같은 영역이 될때까지 나눈다. 같은 영역이 됐다면 count+1을 해준다.
문제 풀이
대표적인 분할정복 문제이다.
로직은 다음과 같다.
1. n값과 시작위치를 입력값으로 받는다.
2. 맵이 시작위치부터 n까지 전부 같은 값으로 이루어져있는지 확인한다.
2-1). 만약 전부 같은 값으로 이루어졌다면, 1인지 0인지 확인하고 해당 숫자를 1증가시켜준다.
3. 사방으로 나누어서 함수를 재귀 호출한다. 이 때, 넘기는 n의 값은 n/2이다.
→ 맵이 전부 같은 지 확인하는 부분을 두 방법으로 풀었다.
1번 방법 )
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(map[x+i][y+j] == 1) b++;
if(map[x+i][y+j] == 0) w++;
}
}
if(b == n*n || w ==n*n ){
if(b>w) blue++;
else white++;
return ;
}
2번 방법 )
if(n==1 || isSame(n,x,y)){
if(map[x][y] == 1) blue++;
if(map[x][y] == 0) white++;
return ;
}
static boolean isSame(int n,int x,int y){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(map[x][y] != map[x+i][y+j]) return false;
}
}
return true;
}
실수한 부분
1. if(b == n*n || w == n*n )
if(b == n*n || w ==n*n ){
if(b>w) blue++;
else white++;
return ;
}
이 부분을 b == n || w == n 으로 실수해서 생각했다.
2. map[x+i][y+i]
static boolean isSame(int n,int x,int y){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(map[x][y] != map[x+i][y+j]) return false;
}
}
return true;
}
이 부분을 map[x+i][x+j] 로 x를 두번 적었다.
코드 1번 풀이
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
static int N;
static int[][] map;
static int blue; // 1
static int white; // 0
public static void main(String[] args) throws FileNotFoundException {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
map = new int[N][N];
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
map[i][j] = sc.nextInt();
}
}
half(N,0,0);
System.out.println(white);
System.out.println(blue);
}
private static void half(int n, int x, int y) {
int b=0;
int w=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(map[x+i][y+j] == 1) b++;
if(map[x+i][y+j] == 0) w++;
}
}
if(b == n*n || w ==n*n ){
if(b>w) blue++;
else white++;
return ;
}
half(n/2,x,y);
half(n/2,x+n/2,y+n/2);
half(n/2,x+n/2,y);
half(n/2,x,y+n/2);
}
}
코드 2번 풀이
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class MainV2 {
static int N;
static int[][] map;
static int blue; // 1
static int white; // 0
public static void main(String[] args) throws FileNotFoundException {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
map = new int[N][N];
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
map[i][j] = sc.nextInt();
}
}
half(N,0,0);
System.out.println(white);
System.out.println(blue);
}
private static void half(int n, int x, int y) {
if(n==1 || isSame(n,x,y)){
if(map[x][y] == 1) blue++;
if(map[x][y] == 0) white++;
return ;
}
half(n/2,x,y);
half(n/2,x+n/2,y+n/2);
half(n/2,x+n/2,y);
half(n/2,x,y+n/2);
}
static boolean isSame(int n,int x,int y){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(map[x][y] != map[x+i][y+j]) return false;
}
}
return true;
}
}
코드 3번 풀이
import java.io.*;
import java.util.StringTokenizer;
public class MainV3 {
static int N;
static int[][] map;
static int blue; // 1
static int white; // 0
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
map = new int[N][N];
for(int i=0;i<N;i++){
StringTokenizer st = new StringTokenizer(br.readLine());
for(int j=0;j<N;j++){
map[i][j] = Integer.parseInt(st.nextToken());
}
}
half(N,0,0);
System.out.println(white);
System.out.println(blue);
}
private static void half(int n, int x, int y) {
if(n==1 || isSame(n,x,y)){
if(map[x][y] == 1) blue++;
if(map[x][y] == 0) white++;
return ;
}
half(n/2,x,y);
half(n/2,x+n/2,y+n/2);
half(n/2,x+n/2,y);
half(n/2,x,y+n/2);
}
static boolean isSame(int n,int x,int y){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(map[x][y] != map[x+i][y+j]) return false;
}
}
return true;
}
}
N이 최대 2^7 ( 128 ) 이라서, bufferedReader를 사용하면 시간이 크게 준다.