은세고화
뚜렷한 기억보단 흐릿한 잉크를
은세고화
전체 방문자
오늘
어제
  • 분류 전체보기 (95)
    • TDD (2)
      • 학점 산출 프로그램 (2)
    • IT (43)
      • 부스트코스 (18)
      • CS50 (3)
      • 도서추천 알고리즘 (2)
      • 스터디 일정 (3)
      • 스프링 (3)
      • 프로젝트 개발 중 발생한 에러 (8)
      • 웹개발 (3)
      • DB (3)
    • 독서 후기 (12)
      • 도서 (12)
    • e북 (3)
    • 알고리즘 (26)
    • 프로젝트 (6)
      • 향수 (6)
    • 회고 (1)

블로그 메뉴

  • 홈

공지사항

인기 글

티스토리

hELLO · Designed By 정상우.
글쓰기 / 관리자
은세고화

뚜렷한 기억보단 흐릿한 잉크를

알고리즘

백준 2580 스도쿠 자바

2022. 3. 19. 11:40
반응형

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

 

2580번: 스도쿠

스도쿠는 18세기 스위스 수학자가 만든 '라틴 사각형'이랑 퍼즐에서 유래한 것으로 현재 많은 인기를 누리고 있다. 이 게임은 아래 그림과 같이 가로, 세로 각각 9개씩 총 81개의 작은 칸으로 이루

www.acmicpc.net

 

nQueen문제를 이해했다면 충분히 풀 수 있는 문제다.

쉽게 풀진 못했고 2가지 케이스 때문에 많은 고생을 했다.

 

접근 아이디어

배열을 입력받을 때 0인 배열의 위치 값을 list에 넣는다. 그 후 백트래킹을 하면서 하나하나 값을 확인한다.

해당 자리에 가능한 숫자 배열을 만들고 그 숫자를 하나하나 넣어가며 백트래킹을 한다.

 

다른 분 코드를 보니 배열을 만들지 않고 숫자를 넣어서 체크하던데 그 방식이 공간 복잡도는 훨씬 줄일 수 있겠다.

 

	static boolean[] getPossibleNum(int y, int x) {
		boolean[] possibleNum = new boolean[10];
		
		//작은 배열에서 넣을 수 있는 숫자 계산
		for (int i = (y/3) * 3; i < (y/3) * 3 + 3 ; i++) {
			for (int j = (x/3) * 3; j < (x/3) * 3 + 3; j++) {
				possibleNum[map[i][j]] = true;
			}
		}
		
		//큰 배열에서 넣을 수 있는 값 계산
		for (int i = 0; i < 9; i++) {
			possibleNum[map[i][x]] = true;
			possibleNum[map[y][i]] = true;
		}
		
		
		//해당자리의 n이 가질 수 있는 값 리스트가 리턴됨
		return possibleNum;
		
		
	}

해당 자리에 2,3,4가 들어간다면 2,3,4 배열만 false다.

 

그리고 1부터 10까지 해당 숫자를 다 넣어보면서 재귀를 수행한다.

for (int i = 1; i < 10; i++) {
			if(!possibleNum[i]) {
				map[p.y][p.x] = i;
				sdoku(n+1);
			}
		}

 

잘 한 부분

해당 자리에 넣을 수 있는 숫자를 계산하는 부분을 어렵지 않게 작성했고. 예제 케이스는 쉽게 통과했다. 

nQueen문제를 이해하고 풀어서 백트래킹 설계를 잘했다.

 

부족한 부분

백트래킹을 수행하고 실패했다면 0으로 만들어줘야 한다. 이 부분을 놓쳐서 많은 시간을 소비했다. 

0으로 만드는 코드를 넣는 곳을 선별하는 것도 쉽지 않았다. 막연히 if(!possibleNum[i[) else {이곳}

 

에다 넣으면 해결되는 줄 알았는데 틀렸다. for문 바깥에 0으로 만드는 코드를 삽입해서 해결했지만 아직 그 차이를 이해하지 못했다.

 

두 번째는 시스템 종료 구문이다. 한 번만 출력해야 하니 한번 출력하고 시스템을 종료해야 한다. 나는 스택에 쌓인 함수를 한 번에 종료할 수 있는 방법이 있는 줄 알고 한참을 고민했는데 그냥 시스템을 종료해야 했다. 조금 황당했고 정답률 이 왜 낮은지 알 수 있었다.

 

세 번째는 공간 복잡도다. 다른 분의 코드보다 조금 빠르지만 공간은 4배나 잡아먹는다. 아마 list를 선언하는 부분과 가능한 숫자를 boolean배열로 받아오는 부분에서 문제가 발생한 것 같다.

또한 문제를 쪼개서 가로, 세로, 작은 네모 이렇게 비교해가며 해결할 수 있었는데 한 번에 모든 숫자를 찾아서 해결하려고 했다. 문제를 쪼개는 습관을 길러야 한다!

 

package backjon;

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

public class Main {
	
	static int T;
	static int[][] map;
	static List<Place> list = new ArrayList<>();
	
	
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		map = new int[9][9];
		for (int i = 0; i < 9; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			for (int j = 0; j < 9; j++) {
				int n = Integer.parseInt(st.nextToken());
				map[i][j] = n;
				if(n == 0) list.add(new Place(i, j));
			}
		}
		sdoku(0);
	}
	
	
	private static void sdoku(int n) {
		if(n == list.size()) {
			for (int i = 0; i < 9; i++) {
				for (int j = 0; j < 9; j++) {
					System.out.print(map[i][j] + " ");
				}
				System.out.println();
			}
			System.exit(0);
			return;
		}

		
		Place p = list.get(n);
		boolean[] possibleNum = getPossibleNum(p.y, p.x);
		
		for (int i = 1; i < 10; i++) {
			if(!possibleNum[i]) {
				map[p.y][p.x] = i;
				sdoku(n+1);
			}
		}
		map[p.y][p.x] = 0;
		
	}
	
	static boolean[] getPossibleNum(int y, int x) {
		boolean[] possibleNum = new boolean[10];
		
		//작은 배열에서 넣을 수 있는 숫자 계산
		for (int i = (y/3) * 3; i < (y/3) * 3 + 3 ; i++) {
			for (int j = (x/3) * 3; j < (x/3) * 3 + 3; j++) {
				possibleNum[map[i][j]] = true;
			}
		}
		
		//큰 배열에서 넣을 수 있는 값 계산
		for (int i = 0; i < 9; i++) {
			possibleNum[map[i][x]] = true;
			possibleNum[map[y][i]] = true;
		}
		
		
		//해당자리의 n이 가질 수 있는 값 리스트가 리턴됨
		return possibleNum;
		
		
	}


	static class Place{
		int y, x;

		public Place(int y, int x) {
			this.y = y;
			this.x = x;
		}
	}

}
반응형
저작자표시

'알고리즘' 카테고리의 다른 글

백준 14889 자바 스타트와 링크  (0) 2022.03.22
백준 14888 자바 연산자 끼워넣기  (0) 2022.03.22
백준 9663 N-Queen 자바  (0) 2022.03.17
프로그래머스 주차요금계산 자바  (0) 2022.03.16
백준 2470 자바 드래곤 커브  (0) 2022.03.09
    '알고리즘' 카테고리의 다른 글
    • 백준 14889 자바 스타트와 링크
    • 백준 14888 자바 연산자 끼워넣기
    • 백준 9663 N-Queen 자바
    • 프로그래머스 주차요금계산 자바
    은세고화
    은세고화

    티스토리툴바