root/eda/codi/backtracking/sudoku.cpp

Revision 145, 2.7 KB (checked in by gunman, 3 years 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
5using namespace std;
6
7int N, N2, W;
8int ** tauler, solucions = 0;
9
10void 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
39bool 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
45bool 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
51bool 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?
64bool 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
70void 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
87int 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.