관리 메뉴

어읽로꾸거

BOJ 2580 2239 스도쿠 본문

알고리즘

BOJ 2580 2239 스도쿠

어읽로꾸거 2019. 3. 23. 03:51

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

백준 2239 : https://www.acmicpc.net/problem/2239

두 문제는 입력과 출력만 다를 뿐 같은 문제라고 봐도 된다.


지하철을 타면서 긴 시간을 통학하는게 지겨워 핸드폰에 스도쿠앱을 깔아서 하고있다. 정말 어려운것 같다. 답답하던 마음에 백준에 마침 스도쿠 문제가 있다는게 떠올라서 풀어보았다.


해결과정:

전체적인 풀이는 재귀를 이용한 완전탐색으로 풀었다는게 핵심이다. 

사람이 푸는것과 마찬가지로 풀었다. 가로, 세로, 사각형에 같은 수가 있는지를 판단하는것이다.

O(1)을 위해 메모이제이션을 이용하였다. 

row 를 예시로 들어서 row[n][number]는 n번째 세로줄에 number가 있는지 여부이다. 양수이면 존재

square은 9x9판을

1 2 3

4 5 6

7 8 9

로 나눠서 square[n][number] n번째 사각형에 number가 있는지 여부이다.


그리고 find함수로 완전탐색을 하였다. flag 변수를 두어 판이 다 채워졌는지를 확인해 불필요한 탐색을 막는다.


코드: (2580기준)

#include<iostream>
using namespace std;
int map[12][12], row[10][10], col[10][10], square[10][10], flag;

void find(int y, int x) {
	if (y == 9 && x == 10) flag = 1;
	else if (x == 10) find(y + 1, 1);
	else if (!map[y][x]) { //빈칸임?
		for (int i = 1; i <= 9; i++) {
			if (!row[y][i] && !col[x][i] && !square[((x + 2) / 3) + (((y - 1) / 3) * 3)][i]) {
				map[y][x] = i; // i 대입
				row[y][i] = col[x][i] = square[((x + 2) / 3) + (((y - 1) / 3) * 3)][i] = 1;
				find(y, x + 1);
				if (flag) break; //만약 스도쿠 다채워지면 도망치기
				map[y][x] = 0;
				row[y][i] = col[x][i] = square[((x + 2) / 3) + (((y - 1) / 3) * 3)][i] = 0;
			}
		}
	}
	else find(y, x + 1);
}

int main() {
	//freopen("input.txt", "r", stdin);
	for (int i = 1; i <= 9; i++) {
		for (int j = 1; j <= 9; j++) {
			cin >> map[i][j];
			row[i][map[i][j]] = 1;
			col[j][map[i][j]] = 1;
			square[((j + 2) / 3) + (((i - 1) / 3) * 3)][map[i][j]] = 1;
		}
	}
	find(1, 1);
	for (int i = 1; i <= 9; i++) {
		for (int j = 1; j <= 9; j++) {
			cout << map[i][j] <<' ';
		}
		cout << endl;
	}
}


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

BOJ 16469 소년 점프  (0) 2019.03.28
BOJ 16953 A → B  (0) 2019.03.27
BOJ 1932 정수 삼각형  (0) 2019.03.26
BOJ 1620 나는야 포켓몬 마스터 이다솜  (0) 2019.03.24
BOJ 15954 인형들  (0) 2019.03.19