[Hdu1017] exact cover [DLX] [dancing links] [annotation Routine learning method]

Source: Internet
Author: User

Dancing links solves the exact cover problem.

The circular bidirectional cross linked list is used.

DFS.

I read this article, found an AC source code, and used the annotation method to help me understand it.

Hit ACM

Thanks to the source code Po master. The link is as follows:

Http://blog.csdn.net/yysdsyl/article/details/4266876

# Include <iostream> # include <cstdio> using namespace STD; const int int_max = 2147483647; struct point {int L; int R; int U; int D; // four-direction linked list int sum; int X, Y;} p [1010*1010]; // This is a point type array directly opened, not reused. 1000*1000 one-dimensional // The linked list here does not dynamically allocate memory, but a static array, only the information they provide allows the elements in the // array to run int n, m; int I, j, k; int map [1001] [1001] According to the function of the linked list. int sor [1001]; int flag; int stack [1001], top; int num (int x, int y) {// converts two dimensions to one-dimensional return x * 1001 + Y;} // delete column C // the so-called "delete" is to change the link between linked lists and searches! Void covercol (INT c) {int I, j; P [p [C]. r]. L = P [C]. l; P [p [C]. l]. R = P [C]. r; // first delete column C's 0th rows // Delete each row with 1 in Column C I = C; for (I = P [I]. d; I! = C; I = P [I]. d) {// end condition: Because the vertical direction is also cyclical. this shows the convenience of the circular linked list J = I; // I is the downward moving P [p [I]. y]. sum --; // actually P [C]. sum --; (regards y as R .. therefore, it cannot be understood as = B) for (j = P [J]. r; J! = I; j = P [J]. r) {// because it is a circular linked list, you can go to the left right until you go all the way [p [J]. d]. U = P [J]. u; P [p [J]. u]. D = P [J]. d ;}}// restore the void release (int c) of column c {// restore a column by providing the number of columns int I, j; P [p [C]. r]. L = C; // The number of columns can address 0th rows P [p [C]. l]. R = C; // restore each row in Column C with 1 I = C; for (I = P [I]. u; I! = C; I = P [I]. u) {// actually the loop is up... the effect is not bad. j = I; P [p [I]. y]. sum ++; For (j = P [J]. l; J! = I; j = P [J]. l) {P [p [J]. d]. U = J; P [p [J]. u]. D = J ;}}// normal DFS is recursive bool DFS (int K) {int I, j; If (FLAG) return 1; // The Return Value of DFS is a bool. // the final result is returned. After the stack is released ~~~ If (P [0]. R = 0) {printf ("% d", top); for (I = 0; I <top; I ++) printf ("% d ", stack [I]); puts (""); // comes with Endl .. flag = 1; return 1;} int C = 0; // each time a column that is not overwritten and has the smallest number of 1 is retrieved, it is used to save the result int min = int_max; // secure min initialization method // I = C; for (I = P [0]. r; I; I = P [I]. r) {// I is a column pointer, traversing. * ** the purpose of 0.0 is to initialize it here! So its left pointer is useless if (P [p [I]. y]. sum <min) {// 0th rows are mainly used to traverse the column min = P [p [I]. y]. SUM; C = I ;}// Delete this column and delete all rows with 1 covercol (c); I = C; // enumerate each row in Column C with 1 and I move down for (I = P [I]. d; I! = C; I = P [I]. d) {// you can still see the loop // P [I]. X acts as the row of the current enumeration and goes to the stack [top ++] = P [I]. x; // top points to the position above the top element of the stack. Because top indicates the number, j = I is equal to the subscript./***** for the enumerated row, delete the column ***** in which the grid of 1 on the row is located. // In fact, this enumeration is a kind of calibration, indicating the selected path (using the characteristics of recursion itself, enumeration (calibration ). // It actually exists./** "delete" is only separated from the subject. ** // the subject is the header pointer to which the // row itself is connected for (j = P [j]. r; J! = I; j = P [J]. r) {covercol (P [J]. y);} If (DFS (k + 1) return 1;/** but why recursion at this time ?? ** // ** Under normal circumstances, it is possible to reach the end point, that is, starting from the current layer call, a non-empty matrix, in general (not limited to N rows and 1 column), it will be completely empty. therefore, when you delete the column, perform the next recursion ** //. In this case, the column is randomly selected and the row is enumeration, that is to say, it is actually a kind of search // [finally we can see that DLX is a kind of search = B] // only the state transfer is determined based on the cross linked list, we are familiar with the square or six-party move). All the items that can be deleted will be deleted to determine whether/or not they have reached the end point. If yes, they will be deleted successfully. Otherwise, select the next column (minimum column + move, in fact, it is to find a solution from the remaining State to find one of its deep search // policies) // also, the recursive feature: the function of this layer is K, then it contains k + 1 calls. // you can view what has been done after the K-layer function runs to "call k + 1, we can see the echo at the beginning of the function. // We can analyze a recursive function in two cases: // 1. assume that the recursive call in the function returns the recursive cutoff data (refer to the baseline information ), Specify the end point. // 2. assume that the recursive call in the function returns the failed data (sometimes, some do not have recursion), and what is the returned path? // if this is the case, it cannot be deleted (return 0 for each layer below) // For This enumerated row, restore the column where the grid of 1 on the row is located/** restore, that is, trace back ** // imagine, just like a volume ~ @ J = I; for (j = P [J]. L; J! = I; j = P [J]. l) {// loop left-side release (P [J]. y);} top --; // Enumeration failed, pop off. this type of enumeration is different each time, and no need to judge the weight} // restore C Release (c); Return 0;} int main () {int T = 0; // special mark of each loop. You do not need to clear the while (scanf ("% d", & N, & M) every time )! = EOF) {T ++; for (I = 1; I <= N; I ++) {// a row is processed by scanf ("% d ", & K); // The number of 1 for (j = 0; j <K; j ++) {scanf ("% d", & sor [J]); // an array map for storing raw data [I] [sor [J] = T; // restore the source image on the map. mark with T !!} Int lef = num (I, SOR [0]); // convert it to the subscript int rig = num (I, SOR [k-1]) of the leftmost and rightmost 1 after one dimension; // The process of assigning values to an array is actually the process of establishing a linked list p [lef]. L = rig; // the pointer is actually a subscript P [lef]. X = I; P [lef]. y = sor [0]; // coordinate in the graph for (j = 1; j <K; j ++) {int cur = num (I, sor [J]); // cyclically retrieve the 1's P [num (I, SOR [J-1]) after the header node]. R = cur; // connect the right pointer of the previous node to P [cur]. L = num (I, SOR [J-1]); // connect the left pointer of the new node to P [cur]. X = I; P [cur]. y = sor [J];} p [rig]. R = lef; // The right pointer of the End Node loops up} // at this point, The cyclic two-way linked list of each row of the entire graph is created ~, Sum is not assigned a value. The default value is 0 p [0]. R = 1; // The graph starts from row 1st. The right pointer of the row 0th points to 1 (also 0th rows )??? // What are the advantages of Row 3 ?? [In the following text] // The left pointer of 0 is not looping up. [In the latter text, comment in the function] for (I = 1; I <= m; I ++) {int NO = num (0, I); // actually I itself... if (I + 1 <= m) // caution! The first column is useless! P [No]. R = num (0, I + 1); else P [No]. r = 0; // The right pointer loops up. // create a linked list for 0th rows. 0.0 is a cyclic point, and all links are connected without crossing the border. P [No]. L = num (0, I-1); P [No]. X = 0; P [No]. y = I; P [No]. sum = 0; // What is sum used? [Later] int last = no; // No is the current column pointer for (j = 1; j <= N; j ++) {// when the column is certain, search for each row if (Map [J] [I] = T) {// if this bit has 1 P [last]. sum ++; // The sum member of The 0th row node stores the 1 Number of the row int now = num (J, I); // convert two-dimensional to one-dimensional. // start to build a cross linked list ~~ P [No]. D = now; // select a node connected to 1 in front of the vertical direction [now]. U = no; // two-way cross linked list No = now; // The last update, that's why it is called 'last '!!!} P [No]. d = num (0, I); P [num (0, I)]. U = no; // vertical loop up if (! P [last]. sum) {// if all columns are 0, it is not possible to accurately overwrite them. Directly exit printf ("No/N"); break ;}} if (I = m + 1) {// exit normally (natural limitation, no variable to mark, good !) Flag = 0; Top = 0; DFS (0); // DLX is a deep search... If (! Flag) puts ("no");} // If the exit is not normal, a judgment has been made.} return 0;}/** conclusion: DLX uses a cyclic bidirectional cross-linked list based on static Arrays for "easy recovery" and its ease of storing sparse matrices, which can effectively solve the problem of precise coverage. **/

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.