Advertisement
Guest User

Untitled

a guest
May 27th, 2018
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.36 KB | None | 0 0
  1. // Буняева В.
  2.  
  3. #include <iostream>
  4. #include <vector>
  5. #include <algorithm>
  6.  
  7. #include "ReadWriter.h"
  8.  
  9. namespace exact_cover
  10. {
  11.  
  12. namespace
  13. {
  14. struct element
  15. {
  16.     element* left;
  17.     element* right;
  18.  
  19.     element* up;
  20.     element* down;
  21.  
  22.     int i_row = -1;
  23.  
  24.     element* col = nullptr;
  25.  
  26.     element() : left(this), right(this), up(this), down(this)
  27.     {}
  28.  
  29.     void remove_hor()
  30.     {
  31.         // Remove the element from a horizontal (left-right) list
  32.  
  33.         left->right = right;
  34.         right->left = left;
  35.     }
  36.  
  37.     void remove_ver()
  38.     {
  39.         // Remove the element from a vertical (top-down) list
  40.  
  41.         up->down = down;
  42.         down->up = up;
  43.     }
  44.  
  45.     void put_back_hor()
  46.     {
  47.         // Undo the effect of `this->remove_hor()`
  48.  
  49.         left->right = this;
  50.         right->left = this;
  51.     }
  52.  
  53.     void put_back_ver()
  54.     {
  55.         // Undo the effect of `this->remove_ver()`
  56.  
  57.         up->down = this;
  58.         down->up = this;
  59.     }
  60.  
  61.     void cover_all_cols()
  62.     {
  63.         // (For a row element) cover all columns that other elements on this row are set for
  64.  
  65.         for(element* cel = right; cel != this; cel = cel->right) {
  66.             cel->col->cover_this_col();
  67.         }
  68.     }
  69.  
  70.     void uncover_all_cols()
  71.     {
  72.         // Undo the effect of `this->cover_all_cols()`
  73.  
  74.         for(element* cel = left; cel != this; cel = cel->left) {
  75.             cel->col->uncover_this_col();
  76.         }
  77.     }
  78.  
  79.     void cover_this_col()
  80.     {
  81.         // (For a column header) completely remove all rows that are set for this column
  82.  
  83.         remove_hor();
  84.  
  85.         for(element* rel = down; rel != this; rel = rel->down) {
  86.             for(element* el = rel->right; el != rel; el = el->right) {
  87.                 el->remove_ver();
  88.             }
  89.         }
  90.     }
  91.  
  92.     void uncover_this_col()
  93.     {
  94.         // Undo the effect of `this->cover_this_col()`
  95.  
  96.         for(element* rel = up; rel != this; rel = rel->up) {
  97.             for(element* el = rel->left; el != rel; el = el->left) {
  98.                 el->put_back_ver();
  99.             }
  100.         }
  101.  
  102.         put_back_hor();
  103.     }
  104. };
  105.  
  106. struct solution
  107. {
  108.     std::vector<int> ix_rows;
  109.     bool found_solution = false;
  110.  
  111.     element* root;
  112.  
  113.     explicit solution(element* root) : root(root)
  114.     {}
  115.  
  116.     void search()
  117.     {
  118.         if(root == root->right) {
  119.             found_solution = true;
  120.  
  121.             return;
  122.         }
  123.  
  124.         element* col = root->right;
  125.  
  126.         col->cover_this_col();
  127.  
  128.         for(element* rel = col->down; rel != col; rel = rel->down) {
  129.             ix_rows.push_back(rel->i_row);
  130.  
  131.             rel->cover_all_cols();
  132.  
  133.             search();
  134.  
  135.             rel->uncover_all_cols();
  136.  
  137.             if(found_solution) {
  138.                 break;
  139.             }
  140.  
  141.             ix_rows.pop_back();
  142.         }
  143.  
  144.         col->uncover_this_col();
  145.     }
  146. };
  147. }
  148.  
  149. /**
  150.  * Solve the exact cover problem
  151.  * @param matrix A matrix where rows constitute subsets, and matrix[i][j] = { ith subset contains }
  152.  * @return If the solution is found, indices in the original matrix of selected subsets. Otherwise, undefined
  153.  */
  154. std::vector<int> get_exact_cover(const std::vector<std::vector<bool>>& matrix)
  155. {
  156.     const size_t n_rows = matrix.size();
  157.     const size_t n_cols = matrix[0].size();
  158.  
  159.     element* root = new element;
  160.  
  161.     {
  162.         // Column headers
  163.         std::vector<element*> cols;
  164.  
  165.         for(int i = 0; i < n_cols; i++) {
  166.             element* col = new element;
  167.  
  168.             col->left = root->left;
  169.             col->right = root;
  170.  
  171.             col->put_back_hor();
  172.  
  173.             cols.push_back(col);
  174.         }
  175.  
  176.         // Leftmost (in order of column indices) element of every row
  177.         std::vector<element*> rows((size_t)n_rows, nullptr);
  178.  
  179.         for(int i_row = 0; i_row < n_rows; i_row++) {
  180.             for(int i_col = 0; i_col < n_cols; i_col++) {
  181.                 if(!matrix[i_row][i_col]) {
  182.                     continue;
  183.                 }
  184.  
  185.                 element* el = new element;
  186.  
  187.                 el->i_row = i_row;
  188.  
  189.                 // Connect the element with its column -- put at the bottom
  190.  
  191.                 el->col = cols[i_col];
  192.  
  193.                 el->up = cols[i_col]->up;
  194.                 el->down = cols[i_col];
  195.  
  196.                 el->put_back_ver();
  197.  
  198.                 // Connect the element with its row -- put at the right
  199.  
  200.                 if(rows[i_row] == nullptr) {
  201.                     rows[i_row] = el;
  202.  
  203.                     el->left = el;
  204.                     el->right = el;
  205.                 }
  206.  
  207.                 el->left = rows[i_row]->left;
  208.                 el->right = rows[i_row];
  209.  
  210.                 el->put_back_hor();
  211.             }
  212.         }
  213.     }
  214.  
  215.     solution s(root);
  216.  
  217.     s.search();
  218.  
  219.     {
  220.         // Delete the whole data structure
  221.  
  222.         element* next_col;
  223.  
  224.         for(element* col = root->right; col != root; col = next_col) {
  225.             element* next_el;
  226.  
  227.             for(element* el = col->down; el != col; el = next_el) {
  228.                 next_el = el->down;
  229.  
  230.                 delete el;
  231.             }
  232.  
  233.             next_col = col->right;
  234.  
  235.             delete col;
  236.         }
  237.  
  238.         delete root;
  239.     }
  240.  
  241.     return s.ix_rows;
  242. }
  243.  
  244. }
  245.  
  246. namespace sudoku
  247. {
  248.  
  249. namespace
  250. {
  251. /**
  252.  * Size of the Sudoku problem -- which is undefined for anything other than 9
  253.  */
  254. const int N = 9;
  255.  
  256. /**
  257.  * Length of a box's side in the Sudoku problem
  258.  */
  259. const int N_BOX = 3;
  260.  
  261. /**
  262.  * Represents the action of setting a specific Sudoku cell to a specific value
  263.  */
  264. struct possibility
  265. {
  266.     /**
  267.      * Coordinates of the cell that the value is assigned to
  268.      */
  269.     const int i_row, i_col;
  270.  
  271.     /**
  272.      * The value that is assigned to the specified cell
  273.      */
  274.     const char value;
  275.  
  276.     /**
  277.      * Apply the possibility to the specified Sudoku field
  278.      * @param field The Sudoku field (an `N` by `N` array)
  279.      */
  280.     void apply(char** const field) const
  281.     {
  282.         field[i_row][i_col] = value;
  283.     }
  284. };
  285.  
  286. /**
  287.  * Calculate whether each Sudoku constraint applies for the specified possibility
  288.  * @param p The possibility
  289.  * @return The values of the constraints' predicates in a specific, but opaque order
  290.  */
  291. std::vector<bool> calculate_constraints(const possibility& p)
  292. {
  293.     std::vector<bool> values;
  294.  
  295.     // Cell constraints (i.e. only one of any digit in every cell)
  296.     for(int i_row = 0; i_row < N; i_row++) {
  297.         for(int i_col = 0; i_col < N; i_col++) {
  298.             values.push_back(p.i_row == i_row && p.i_col == i_col);
  299.         }
  300.     }
  301.  
  302.     // Row constraints (i.e. one of each digit in every row)
  303.     for(int i_row = 0; i_row < N; i_row++) {
  304.         for(char c = '1'; c <= '9'; c++) {
  305.             values.push_back(p.i_row == i_row && p.value == c);
  306.         }
  307.     }
  308.  
  309.     // Column constraints
  310.     for(int i_col = 0; i_col < N; i_col++) {
  311.         for(char c = '1'; c <= '9'; c++) {
  312.             values.push_back(p.i_col == i_col && p.value == c);
  313.         }
  314.     }
  315.  
  316.     // Box constraints
  317.     for(int i_brow = 0; i_brow < N / N_BOX; i_brow++) {
  318.         for(int i_bcol = 0; i_bcol < N / N_BOX; i_bcol++) {
  319.             for(char c = '1'; c <= '9'; c++) {
  320.                 values.push_back(
  321.                         p.i_row / N_BOX == i_brow && p.i_col / N_BOX == i_bcol && p.value == c
  322.                 );
  323.             }
  324.         }
  325.     }
  326.  
  327.     return values;
  328. }
  329. }
  330.  
  331. /**
  332.  * Fill the empty cells on the specified Sudoku field such that the field is solved. If the field is not solvable, the
  333.  * behavior is undefined
  334.  * @param field The Sudoku field -- a 9 by 9 array of ASCII characters '1' through '9' and '+' for empty cells
  335.  */
  336. void solve_sudoku_field(char** const field)
  337. {
  338.     std::vector<possibility> possibilities;
  339.  
  340.     for(int i_row = 0; i_row < N; i_row++) {
  341.         for(int i_col = 0; i_col < N; i_col++) {
  342.             if(field[i_row][i_col] != '+') {
  343.                 possibilities.push_back({ i_row, i_col, field[i_row][i_col] });
  344.             }
  345.             else {
  346.                 for(char c = '1'; c <= '9'; c++) {
  347.                     possibilities.push_back({ i_row, i_col, c });
  348.                 }
  349.             }
  350.         }
  351.     }
  352.  
  353.     std::vector<std::vector<bool>> constraint_values(possibilities.size());
  354.  
  355.     std::transform(possibilities.begin(), possibilities.end(), constraint_values.begin(), calculate_constraints);
  356.  
  357.     std::vector<bool> is_selected(possibilities.size(), false);
  358.  
  359.     for(int i_p : exact_cover::get_exact_cover(constraint_values)) {
  360.         is_selected[i_p] = true;
  361.     }
  362.  
  363.     for(int i_p = 0; i_p < possibilities.size(); i_p++) {
  364.         if(!is_selected[i_p]) {
  365.             continue;
  366.         }
  367.  
  368.         possibilities[i_p].apply(field);
  369.     }
  370. }
  371.  
  372. }
  373.  
  374. //Основной метод решения задачи, параметры:
  375. //n - размер исходной задачи и результата (NxN)
  376. //field - матрица NxN, не до конца заполненное поле, содержит цифры и символы '+', как пустое место, которое надо заполнить
  377. //Если так будет удобнее, то можно удалить этот массив, создать новый(такого же размера) и перенаправить указатель (для этого указатель передается как char**&)
  378. //Требуется не допускать утечек памяти! Проверьте перед сдачей, так как в одной из работ это была наиболее частая ошибка.
  379. void solve_sudoku(char**& field, int n)
  380. {
  381.     sudoku::solve_sudoku_field(field);
  382. }
  383.  
  384. int main()
  385. {
  386.     using namespace std;
  387.  
  388.     ReadWriter rw;
  389.     //Входные параметры
  390.     int n = rw.readInt();
  391.     //Массив для матрицы
  392.     char** arr = new char*[n];
  393.     for (int i = 0; i < n; i++)
  394.         arr[i] = new char[n];
  395.  
  396.     //Чтение матрицы
  397.     rw.readMatrix(arr, n, n);
  398.  
  399.     //Алгоритм решения судоку, ответ в тот же массив, где и была разреженная матрица
  400.     solve_sudoku(arr, n);
  401.  
  402.     //Выводим результаты
  403.     rw.writeInt(n);
  404.     rw.writeMatrix(arr, n, n);
  405.  
  406.     //Освободим память
  407.     for (int i = 0; i<n; i++)
  408.         delete[] arr[i];
  409.     delete[] arr;
  410.  
  411.     return 0;
  412. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement