ExactCover.cpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. const int maxn = 1000;
  2. const int maxnode = 1000;
  3. const int maxr = 1000;
  4. // l'algorithme X + Dancing links.
  5. struct DLX {
  6. int n, sz; //nb de colonne, nb de noeuds.
  7. int S[maxn]; //nb de noeuds dans chaque colonne.
  8. int row[maxnode], col[maxnode]; // index de ligne et colonne pour chaque noeud.
  9. int L[maxnode], R[maxnode], U[maxnode], D[maxnode];
  10. int ansd, ans[maxr]; //solution
  11. void init(int n) {
  12. this->n = n;
  13. // noeud virtuel
  14. for(int i = 0 ; i <= n; i++) {
  15. U[i] = i; D[i] = i; L[i] = i-1, R[i] = i+1;
  16. }
  17. R[n] = 0; L[0] = n;
  18. sz = n + 1;
  19. memset(S, 0, sizeof(S));
  20. }
  21. void addRow(int r, VI columns) {
  22. int first = sz;
  23. for(int i = 0; i < columns.size(); i++) {
  24. int c = columns[i];
  25. L[sz] = sz - 1; R[sz] = sz + 1; D[sz] = c; U[sz] = U[c];
  26. D[U[c]] = sz; U[c] = sz;
  27. row[sz] = r; col[sz] = c;
  28. S[c]++; sz++;
  29. }
  30. R[sz - 1] = first; L[first] = sz - 1;
  31. }
  32. #define FOR(i,A,s) for(int i = A[s]; i != s; i = A[i])
  33. void remove(int c) {
  34. L[R[c]] = L[c];
  35. R[L[c]] = R[c];
  36. FOR(i,D,c)
  37. FOR(j,R,i) { U[D[j]] = U[j]; D[U[j]] = D[j]; --S[col[j]]; }
  38. }
  39. void restore(int c) {
  40. FOR(i,U,c)
  41. FOR(j,L,i) { ++S[col[j]]; U[D[j]] = j; D[U[j]] = j; }
  42. L[R[c]] = c;
  43. R[L[c]] = c;
  44. }
  45. bool dfs(int d) { //d : depth
  46. if (R[0] == 0) { // Found the solution
  47. ansd = d; // the length of the solution
  48. return true;
  49. }
  50. // Find the column c which has the minimum S.
  51. int c = R[0]; //the first column non-deleted
  52. FOR(i,R,0) if(S[i] < S[c]) c = i;
  53. remove(c);
  54. FOR(i,D,c) {
  55. ans[d] = row[i];
  56. FOR(j,R,i) remove(col[j]); //Delete all columns covered by i-th line.
  57. if(dfs(d+1)) return true;
  58. FOR(j,L,i) restore(col[j]); // Undo
  59. }
  60. restore(c);
  61. return false;
  62. }
  63. bool solve(VI& v) {
  64. v.clear();
  65. if(!dfs(0)) return false;
  66. for(int i = 0; i < ansd; i++) v.push_back(ans[i]);
  67. return true;
  68. }
  69. };
  70. void test() {
  71. DLX solver;
  72. solver.init(7);
  73. // parmi ces 6 ensembles, existe-t-il une couverture exacte de 1..7?
  74. VI v1 = {1,4,7}; VI v2 = {1,4}; VI v3 = {4,5,7};
  75. VI v4 = {3,5,6}; VI v5 = {2,3,6,7}; VI v6 = {2,7};
  76. solver.addRow(1, v1); solver.addRow(2, v2); solver.addRow(3, v3); solver.addRow(4, v4); solver.addRow(5, v5); solver.addRow(6, v6);
  77. VI ans;
  78. solver.solve(ans);
  79. for (int i = 0; i < ans.size(); i++)
  80. cout<< ans[i] << endl;
  81. if (ans.size() == 0)
  82. cout << "Non solution" <<endl;
  83. }