UVa 989

UVa 989

題目

http://domen111.github.io/UVa-Easy-Viewer/?989

跟數獨問題相同,不過這次的版面大小可以從 $1 \times 1$ 到 $3 \times 3$

想法

記錄小正方形、行、列每個數字是否出現過,透過 DFS 枚舉每種可能

Code

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//By Koios1143
#include<iostream>
using namespace std;

int n, R, arr[9][9], nx[81], ny[81];
bool found, out=false, small_sq[9][10], row[9][10], col[9][10];

void init(){
for(int i=0 ; i<9 ; i++){
for(int j=0 ; j<10 ; j++){
small_sq[i][j] = false;
row[i][j] = false;
col[i][j] = false;
}
}
for(int i=0 ; i<n*n ; i++){
for(int j=0 ; j<n*n ; j++){
if(arr[i][j] != 0){
col[j][arr[i][j]]=true;
row[i][arr[i][j]]=true;
small_sq[n*(i/n) + j/n][arr[i][j]]=true;
}
}
}
}

void DFS(int depth){
if(depth == R){
found = true;
for(int i=0 ; i<n*n ; i++){
for(int j=0 ; j<n*n ; j++){
if(j) cout<<' ';
cout<<arr[i][j];
}
cout<<'\n';
}
return;
}
int x = nx[depth];
int y = ny[depth];
for(int i=1 ; i<=n*n && !found ; i++){
if(!col[y][i] && !row[x][i] && !small_sq[n*(x/n) + y/n][i]){
col[y][i] = true;
row[x][i] = true;
small_sq[n*(x/n) + y/n][i] = true;
arr[x][y] = i;
DFS(depth+1);
col[y][i] = false;
row[x][i] = false;
small_sq[n*(x/n) + y/n][i] = false;
arr[x][y] = 0;
}
}
}

int main(){
while(cin>>n){
if(out) cout<<"\n";
else out=true;
R = 0;
found = false;
for(int i=0 ; i<n*n ; i++){
for(int j=0 ; j<n*n ; j++){
cin>>arr[i][j];
if(arr[i][j] == 0){
nx[R] = i;
ny[R] = j;
R++;
}
}
}
init();
DFS(0);
if(!found){
cout<<"NO SOLUTION\n";
}
}

return 0;
}

時間複雜度分析

每筆測資輸入時間複雜度為 $O(n^2 \times n^2)$

DFS 每次最多有 $n^2$ 種選擇,最多有 $n^2 \times n^2$ 層

每筆測資 DFS 時間複雜度為 $O(n^{2^{n^{4}}})$

每筆測資總時間複雜度為 $O(n^4 + n^{2^{n^{4}}})$