코딩문제풀이/Baekjoon

[Java] 백준12100번 : 2048(Easy)

코딩하는 포메라니안 2022. 3. 30. 16:23

1. 문제

https://www.acmicpc.net/problem/12100

 

12100번: 2048 (Easy)

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2

www.acmicpc.net

 

 

 

2. 풀이 과정

처음엔 쉬운 풀이 방법이 있을까 생각하다가, 안 떠올라서 그냥 모든 경우의 수를 다 돌려보고 생각해봐야겠다 하고 구현했는데, 통과가 되었다.

 

위로, 아래로, 왼쪽으로, 오른쪽으로 각각 0, 1, 2, 3으로 생각하고 5개를 뽑는 중복 순열을 만들었다. 선택한 차례대로 함수를 실행시켜 결과를 냈다.

 

 

1) 최대값 구하기

- 처음 값을 입력받을 때, 확인

- 두 값이 같아서 합칠 때, 확인

=> 두 경우만 고려하면 된다.

 

 

2) 네 방향 중 하나로 이동시키기

- 자신이 앞으로 갈 수 있는 위치 = prev

- 지금 보고 있는 위치 = j

 

 

 

 

단계 1) Up, Down, Left, Right를 따로 생성

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Boj12100 {
	static int N, max;
	static int order[], origin[][];
	public static void permutation(int cnt) {
		if(cnt==5) {
			//배열 복사
			int[][] carr = new int[N][N];
			for(int i=0;i<N;i++)
				carr[i] = origin[i].clone();
			
			for(int i=0;i<5;i++) {
				switch(order[i]) {
				case 0:
					goUp(carr);
					break;
				case 1:
					goDown(carr);
					break;
				case 2:
					goLeft(carr);
					break;
				case 3:
					goRight(carr);
					break;
				}
			}
			
			return;
		}
		for(int i=0;i<4;i++) {//4방향 up, down, left, right
			order[cnt]=i;
			permutation(cnt+1);
		}
	}
	
	public static void goUp(int arr[][]) {
		for(int i=0;i<N;i++) {
			int prev = 0;
			for(int j=1;j<N;j++) {
				if(arr[j][i]==0) {
					continue;
				}
				else {
					if(arr[prev][i]==0) {
						arr[prev][i] = arr[j][i];
						arr[j][i] = 0;
					}
					else {
						if(arr[prev][i] == arr[j][i]) {//값이 같으면
							arr[prev][i]*=2;
							arr[j][i] = 0;
							max = Math.max(max, arr[prev][i]);
							prev++;
						}
						else {
							if(++prev != j) {
								arr[prev][i] = arr[j][i];
								arr[j][i] = 0;
							}
						}
					}
				}
			}
		}
	}
	
	public static void goDown(int arr[][]) {
		for(int i=0;i<N;i++) {
			int prev = N-1;
			for(int j=N-2;j>=0;j--) {
				if(arr[j][i]==0) {
					continue;
				}
				else {
					if(arr[prev][i]==0) {
						arr[prev][i] = arr[j][i];
						arr[j][i] = 0;
					}
					else {
						if(arr[prev][i] == arr[j][i]) {//값이 같으면
							arr[prev][i]*=2;
							arr[j][i] = 0;
							max = Math.max(max, arr[prev][i]);
							prev--;
						}
						else {
							if(--prev != j) {
								arr[prev][i] = arr[j][i];
								arr[j][i] = 0;
							}
						}
					}
				}
			}
		}
	}
	
	public static void goLeft(int arr[][]) {
		for(int i=0;i<N;i++) {
			int prev = 0;
			for(int j=1;j<N;j++) {
				if(arr[i][j]==0) {
					continue;
				}
				else {
					if(arr[i][prev]==0) {
						arr[i][prev] = arr[i][j];
						arr[i][j] = 0;
					}
					else {
						if(arr[i][prev] == arr[i][j]) {//값이 같으면
							arr[i][prev]*=2;
							arr[i][j] = 0;
							max = Math.max(max, arr[i][prev]);
							prev++;
						}
						else {
							if(++prev != j) {
								arr[i][prev] = arr[i][j];
								arr[i][j] = 0;
							}
						}
					}
				}
			}
		}
	}
	
	public static void goRight(int arr[][]) {
		for(int i=0;i<N;i++) {
			int prev = N-1;
			for(int j=N-2;j>=0;j--) {
				if(arr[i][j]==0) {
					continue;
				}
				else {
					if(arr[i][prev]==0) {
						arr[i][prev] = arr[i][j];
						arr[i][j] = 0;
					}
					else {
						if(arr[i][prev] == arr[i][j]) {//값이 같으면
							arr[i][prev]*=2;
							arr[i][j] = 0;
							max = Math.max(max, arr[i][prev]);
							prev--;
						}
						else {
							if(--prev != j) {
								arr[i][prev] = arr[i][j];
								arr[i][j] = 0;
							}
						}
					}
				}
			}
		}
	}

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;
		N = Integer.parseInt(br.readLine());
		origin = new int[N][N];
		order = new int[5];//방향 5개 선택
		
		for(int i=0;i<N;i++) {
			st = new StringTokenizer(br.readLine());
			for(int j=0;j<N;j++) {
				origin[i][j] = Integer.parseInt(st.nextToken());
				max = Math.max(max, origin[i][j]);
			}	
		}
		permutation(0);
		System.out.println(max);
	}
}

 

 

 

 

단계 2) Up&Down과 Left&Right를 하나로 묶음

 

묶은 기준은 2차원 배열의 접근 방식이다 Up&Down은 모두 arr[i][j]로 한 열씩 탐색한다면,

Left&Right은 arr[j][i]로 한 행씩 차례로 탐색한다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Boj12100_2 {
	static int N, max;
	static int order[], origin[][];
	public static void permutation(int cnt) {
		if(cnt==5) {
			//배열 복사
			int[][] carr = new int[N][N];
			for(int i=0;i<N;i++)
				carr[i] = origin[i].clone();
			
			for(int i=0;i<5;i++) 
				move(order[i], carr);
				
			return;
		}
		for(int i=0;i<4;i++) {//4방향 up, down, left, right
			order[cnt]=i;
			permutation(cnt+1);
		}
	}
	
	public static void move(int n, int arr[][]) {
		//up, down, left, right
		int start = (n%2==0) ? 0 : N-1;
		int inc = (n%2==0) ? 1 : -1;
		
		if(n<2) {//up & down
			for(int i=0;i<N;i++) {
				int prev = start;
				for(int j=start+inc; 0<=j && j<N; j+=inc) {
					if(arr[j][i]==0) {
						continue;
					}
					else {
						if(arr[prev][i]==0) {
							arr[prev][i] = arr[j][i];
							arr[j][i] = 0;
						}
						else {
							if(arr[prev][i] == arr[j][i]) {//값이 같으면
								arr[prev][i]*=2;
								arr[j][i] = 0;
								max = Math.max(max, arr[prev][i]);
								prev+=inc;
							}
							else {
								prev+=inc;
								if(prev != j) {
									arr[prev][i] = arr[j][i];
									arr[j][i] = 0;
								}
							}
						}
					}
				}
			}
		}
		else {//left & right
			for(int i=0;i<N;i++) {
				int prev = start;
				for(int j=start+inc; 0<=j && j<N; j+=inc) {
					if(arr[i][j]==0) {
						continue;
					}
					else {
						if(arr[i][prev]==0) {
							arr[i][prev] = arr[i][j];
							arr[i][j] = 0;
						}
						else {
							if(arr[i][prev] == arr[i][j]) {//값이 같으면
								arr[i][prev]*=2;
								arr[i][j] = 0;
								max = Math.max(max, arr[i][prev]);
								prev+=inc;
							}
							else {
								prev += inc;
								if(prev != j) {
									arr[i][prev] = arr[i][j];
									arr[i][j] = 0;
								}
							}
						}
					}
				}
			}
		}
	}
	
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;
		N = Integer.parseInt(br.readLine());
		origin = new int[N][N];//벽세움
		order = new int[5];//방향 5개 선택
		
		for(int i=0;i<N;i++) {
			st = new StringTokenizer(br.readLine());
			for(int j=0;j<N;j++) {
				origin[i][j] = Integer.parseInt(st.nextToken());
				max = Math.max(max, origin[i][j]);
			}	
		}
		permutation(0);
		System.out.println(max);
	}
}