• 9X9 크기의 스도쿠를 푸는 문제이다.

문제 풀이

  • 풀어야 하는 곳들을 저장해놓고 그 순서를 따라서 dfs를 돌리면 된다.
소스코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include<bits/stdc++.h>
using namespace std;
typedef vector<int> vi;

int sd[9][9];
vi vl;

int check(int ci, int cj, int v);
int make_pq(){
	for(int i=0;i<9;i++) for(int j=0;j<9;j++){
		if(sd[i][j]) continue;
		vl.push_back(i*10+j);
	}
	if(vl.empty()) return 0;
	return 1;
}
int f(int idx);

int main()
{
	string s;
	for(int i=0;i<9;i++){
		int jidx=0;
		getline(cin, s, '\n');
		while(s=="") getline(cin, s, '\n');
		for(int j=0;j<s.length();j++) if(s[j]!=' ') sd[i][jidx++]=s[j]-48;
	}
	if(make_pq()) f(0);
	s.clear();
	for(int i=0;i<9;i++){
		for(int j=0;j<9;j++){
			s.push_back(sd[i][j]+'0');
			s.push_back(' ');
		}
		s.push_back('\n');
	}
	cout<<s;
}

int check(int ci, int cj, int v){
	for(int i=0;i<9;i++){
		if(sd[ci][i]==v) return 0;
		if(sd[i][cj]==v) return 0;
	}
	for(int i=ci/3*3;i<(ci/3+1)*3;i++) for(int j=cj/3*3;j<(cj/3+1)*3;j++)
		if(sd[i][j]==v) return 0;
	return 1;
}

int f(int idx){
	int ci=vl[idx]/10, cj=vl[idx]%10;
	for(int i=1;i<10;i++){
		if(check(ci, cj, i)){
			sd[ci][cj]=i;
			if(idx+1==vl.size()) return 1;
			if(f(idx+1)) return 1;
		}
		sd[ci][cj]=0;
	}
	return 0;
}

풀고나서

  • 입력이 작기 때문에 그냥 0인 원소들만 뽑아서 [1, 9] 집어넣으면서 테스트하면 대충 O(N^(N^2))이다. (N=10)
    커팅을 하려고 단서가 가장 많은 원소들 순으로 정렬해서 풀려고 했다.(탐색하는 너비가 작아지기 때문) 하지만 정렬하는 과정에서 N^2가 필요하고 탐색할 때마다 N^2의 비용이 들어 결과적으로 O((N^2+N)^(N^2))를 만들어내고 몇 번 TLE가 났다.

  • 54번째 줄을 if문 위로 옮겨서 check(ci, cj)를 호출하면 시간초과가 난다. 시간복잡도가 같아도 TLE가 났었다.(check 함수에서 벡터에 각 숫자 개수 저장하면서 2넘으면 0 반환하는 구조로 만들었었다.)

Leave a comment