코딩테스트/백준

백준 2580 : 스도쿠

Mev01 2020. 9. 14. 15:05

www.acmicpc.net/problem/2580

 

2580번: 스도쿠

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

www.acmicpc.net

접근방법


백트래킹 문제이다.

다른 백트래킹 문제와 조금 다르게 하나의 답만 요구하므로 전체를 다 탐색할 필요가 없다.

또한 전체를 탐색하면서 값을 계속 변경할 경우 잘못된 값이 답에 들어갈 수 있다.

그러므로 빈 공간을 다 채워주는 해를 발견할 경우 바로 출력해야 한다.

 

코드


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
void DFS(int num);
void Promising(int num, int ck[10]);
void Print();

vector<int> x, y;
vector<int> ans[81];
int map[10][10] = { 0, };
int pred[10][10] = { 0, };
int siz = 0;
int Find = 0;

int main()
{
	int a;
	for (int i = 1; i < 10; i++) {
		for (int j = 1; j < 10; j++) {
			cin >> a;
			if (!a) {
				x.push_back(i);
				y.push_back(j);
				siz++;
			}
			map[i][j] = a;
		}
	}
	DFS(0);
}

void DFS(int num) {
	if (num == siz) {  //정답이 완성되면 출력하고 전부 return
		Find = 1;
		Print();
		return;
	}
	int ck[10] = { 0, };
	Promising(num, ck); //유망한지 검사

	for (int i = 1; i < 10; i++) {
		if (ck[i] == 0 && !Find) {
			map[x[num]][y[num]] = i;
			DFS(num + 1);
			map[x[num]][y[num]] = 0;
		}
	}
}

void Promising(int num, int ck[10]) {
	for (int i = 1; i < 10; i++) {	
		ck[map[x[num]][i]]++;	//가로줄 검사
		ck[map[i][y[num]]]++;	//세로줄 검사
	}
	for (int i = (x[num] - 1) / 3 * 3 + 1; i < (x[num] - 1) / 3 * 3 + 4; i++) {	//정사각형 검사
		for (int j = (y[num] - 1) / 3 * 3 + 1; j < (y[num] - 1) / 3 * 3 + 4; j++) {
			ck[map[i][j]]++;
		}
	}
}

void Print() {
	for (int i = 1; i < 10; i++) {
		for (int j = 1; j < 10; j++) {
			cout << map[i][j] << " ";
		}
		cout << "\n";
	}
}

'코딩테스트 > 백준' 카테고리의 다른 글

백준 1202 : 보석 도둑  (0) 2021.06.16
백준 10158 : 개미  (0) 2021.04.18
백준 2293 : 동전 1  (0) 2020.09.21
백준 2108 : 통계학  (0) 2020.09.05
백준 2751 : 수 정렬하기 2  (0) 2020.08.21