간단한 백트래킹을 사용한 구현 문제이다.

로직은 생각보다 간단하다. dfs 순회를 하면서 넣으려는 숫자가

  • 행에 있는지
  • 열에 있는지
  • 박스에 있는지

3가지만 확인하면 된다. 이 때 각각을 전부 순회를 때리게 되면 각각 9번의 연산이 생기게 된다. 그렇게 되면 81번의 공간에 9개의 숫자를 확인하되 각각 27번의 check 연산을 하게 되어 복잡도에 큰 문제가 생기지 않는다고 판단된다.

허나 좀더 빠르게 연산하기 위해 해쉬를 두어 숫자를 체크하게 되면 메모리를 조금 더 두어 check 연산을 O(1) 만큼의 복잡도로 처리할 수 있게 된다.

 

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <tuple>
#include <string>
#include <string.h>
#include <stack>
#include <set>
#include <map>


using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
int doqu[10][10];
int row[10][10];
int col[10][10];
int box[3][3][10];
vector<pii> zero;
bool dfs_check = false;

void do_memo(int tx, int ty, int x, int y, int i) {
	row[x][i] = 1;
	col[i][y] = 1;
	box[tx][ty][i] = 1;
	return;
}
void un_memo(int tx, int ty, int x, int y, int i) {
	row[x][i] = 0;
	col[i][y] = 0;
	box[tx][ty][i] = 0;
	return;
}
void print_doqu() {
	for (int i = 1; i <= 9; i++) {
		for (int j = 1; j <= 9; j++) {
			printf("%d", doqu[i][j]);
		}
		printf("\n");
	}
	return;
}
void dfs(int n) {
	if (dfs_check) return;
	if (n == zero.size()) {
		dfs_check = true;
		print_doqu();
		return;
	}
	int cx = zero[n].first;
	int cy = zero[n].second;
	int tp = 0, tx, ty;
	for (int i = 1; i <= 9; i++) {
		if (row[cx][i] == 1) continue;
		if (col[i][cy] == 1) continue;
		tx = (cx - 1) / 3;
		ty = (cy - 1) / 3;
		if (box[tx][ty][i] == 1) continue;

		tp = doqu[cx][cy];
		doqu[cx][cy] = i;
		do_memo(tx, ty, cx, cy, i);
		dfs(n + 1);
		un_memo(tx, ty, cx, cy, i);
		doqu[cx][cy] = tp;
		
	}
	
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	int tx, ty;
	for (int i = 1; i <= 9; i++) {
		for (int j = 1; j <= 9; j++) {
			scanf(" %1d", &doqu[i][j]);
			if (doqu[i][j] == 0)
				zero.push_back({ i,j });
			else {
				row[i][doqu[i][j]] = 1;
				col[doqu[i][j]][j] = 1;
				tx = (i - 1) / 3;
				ty = (j - 1) / 3;
				box[tx][ty][doqu[i][j]] = 1;
			}
		}
	}
	dfs(0);

	return 0;
}

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

 

2239번: 스도쿠

스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다

www.acmicpc.net

 

'책장 > 알고리즘' 카테고리의 다른 글

[백준-9935] 문자열폭발  (0) 2021.08.19
[백준-2166] 다각형의 면적  (0) 2021.08.19
[백준-2357] 최솟값과 최댓값  (0) 2021.08.16
[백준-2285] 우체국  (0) 2021.08.16