Assembla home | Assembla project page
 

root/eda/codi/backtracking/sudoku.cpp

Revision 145, 2.7 kB (checked in by gunman, 9 months ago)

Afegit codi del sudoku, del knight's tour i de les n-reines.

Line 
1 #include <iostream>
2 #include <fstream>
3 #include <iomanip>
4
5 using namespace std;
6
7 int N, N2, W;
8 int ** tauler, solucions = 0;
9
10 void printSol() {
11   for(int i = 0; i < N2; ++i){
12     // Imprimeix barres horitzontals.
13     if(i % N == 0){
14       for(int j = 0; j < N2; ++j){
15         if(j % N == 0) cout << setw(W) << "+";
16         cout << setw(W) << "-";
17       }
18       cout << setw(W) << "+" << endl;
19     }
20
21     // Imprimeix nombres i barres verticals.
22     for(int j = 0; j < N2; ++j){
23       if(j % N == 0) cout << setw(W) << "|";
24       cout << setw(W) << tauler[i][j];
25     }
26     cout << setw(W) << "|" << endl;
27   }
28  
29   // Imprimeix la última de barres horitzontals i verticals.
30   for(int i = 0; i < N2; ++i){
31     if(i % N == 0){
32       cout << setw(W) << "+";
33     }
34     cout << setw(W) << "-";
35   }
36   cout << setw(W) << "+" << endl << endl;
37 }
38
39 bool factible_h(int f, int c, int k){
40   for(int i = 0; i < N2; ++i)
41     if(tauler[f][i] == k && i != c) return false;
42   return true;
43 }
44
45 bool factible_v(int f, int c, int k){
46   for(int i = 0; i < N2; ++i)
47     if(tauler[i][c] == k && i != f) return false;
48   return true;
49 }
50
51 bool factible_q(int f, int c, int k){
52   int fb = (f / N) * N;
53   int cb = (c / N) * N;
54
55   for(int i = fb; i < fb+N; ++i){
56     for(int j = cb; j < cb+N; ++j){
57       if(tauler[i][j] == k && (i != f || j != c)) return false;
58     }
59   }
60   return true;
61 }
62
63 // És factible com a solució el valor k en la posició i, j?
64 bool factible(int i, int j, int k){
65   return ((tauler[i][j] == 0 || tauler[i][j] == k) &&
66           factible_h(i, j, k) && factible_v(i, j, k) &&
67           factible_q(i, j, k));
68 }
69
70 void sudoku(int f, int c){
71   if(f >= N2){
72     printSol();
73     ++solucions;
74   } else {
75     for(int s = 1; s <= N2; ++s){
76       if(factible(f, c, s)){
77         int prev = tauler[f][c];
78         tauler[f][c] = s;
79         if(c < N2-1) sudoku(f, c+1);
80         else sudoku(f+1, 0);
81         tauler[f][c] = prev;
82       }
83     }
84   }
85 }
86
87 int main(int argc, char ** argv){
88   if(argc != 2){
89     cerr << "Usage: " << argv[0] << " sudoku" << endl;
90     return 1;
91   }
92
93   ifstream file(argv[1]);
94   if(!file){
95     cerr << argv[1] << " could not been opened!" << endl;
96     return 2;
97   }
98
99   file >> N;
100   N2 = N*N;
101
102   // Crea el tauler de N^2 * N^2.
103   tauler = new int* [N2];
104   for(int i = 0; i < N2; ++i)
105     tauler[i] = new int [N2];
106
107   // Llegeix les dades...
108   for(int i = 0; i < N2; ++i){
109     for(int j = 0; j < N2; ++j){
110       file >> tauler[i][j];
111       if(cin.eof()){
112         cerr << "Invalid file!" << endl;
113         return 3;
114       }
115     }
116   }
117
118   W = 1;
119   int t = N2;
120   while(t > 0){
121     t /= 10;
122     W++;
123   }
124  
125   sudoku(0,0);
126  
127   cout << "Hi ha un total de " << solucions << " solucions possibles"
128        << " per a aquest Sudoku." << endl;
129  
130   // Allibera memòria.
131   for(int i = 0; i < N2; ++i)
132     delete [] tauler[i];
133   delete [] tauler;
134  
135   return 0;
136 }
Note: See TracBrowser for help on using the browser.