Easy-to-understand Dancing links (4)

Source: Internet
Author: User
Application of DancingLinks

When dancingLink is applied to actual problems, there is only one difficulty, that is, how to convert a specific problem to a 01 matrix model that can be accurately covered. Once this step is completed, directly apply the template to solve the problem.

One application: 12 computers

12 things are typical for precise coverage of dancing links, which is the easiest to understand.



Figure 2-12 pieces of 5-size bone card puzzle

Description:

I will give you 12 5-frame cards, as shown in the following figure.

Is an answer to the question. Do you know how the program gets this answer? That's right. It's precisely covered by dancinglink.

We imagine a matrix with 72 columns, 12 of which are 12 dominoes, and the remaining 60 columns are the grids of 60 non-central parts.

All possible rows represent a scheme to be placed on a card; each row has a ''1'' to identify the covered grid, 5: 1 identifies the position where a card is placed (there are 1568 such rows)

We name the first 12 columns as F, I, L, P, N, T, U, V, W, X, Y, Z, in addition, we can use two numbers, I and j, to name the column in the matrix corresponding to the column in column j of row I on the chessboard. By giving the names of the columns with '1', you can easily display each row.

For example, Figure 2 shows the exact coverage of the 12 rows below.


1568 rows refer to the total number of 12 Bone card placement schemes. For example, there are 64 placement schemes for long bone card I, and 1568 contains these 64 schemes.

In the 1568 rows, each row has 6 1 columns and is distributed in 72 columns.

The construction idea of this matrix is:

First, find the constraint relationship. Here there are only two constraints,

(1) 12 dominoes, each with only one,

(2) of the 60 spaces, only one type of dominoes can be placed at one position (otherwise, they will overlap)

Because of the first constraint relationship, there are 12 columns to distinguish the type of the dominoes. Because of the second constraint relationship, there are 60 columns and 5 columns to indicate the dominoes placement.

Application 2: Data independence sudoku

The exact coverage can be used to resolve the sudoku and generate the sudoku. It is still difficult to construct the sudoku problem into a 01 matrix.

First, find the constraint relationship. Here there are only four constraints,

(1) only one number can be placed in each of the 81 grids.

(2) numbers in each row cannot be repeated.

(3) numbers in each column cannot be repeated.

(4) numbers in the ninth Palace cannot be repeated.


In the four constraint relationships, each constraint corresponds to a column field. For the second constraint relationship, there are 9 rows in the number of single-digit pairs. You can enter 9 different numbers in each row.

Therefore, the second column field has a total of 9*9 and 81 columns. Therefore, there are a total of 324 columns for the sudoku problem.

Because there are 81 grids, each of which has a maximum of 9 options, there can be a maximum of 81*9 = 729 rows.

In this way, each row of the 01 matrix has four 1, the first 1 is distributed in columns 1 to 81, and the second 1 is distributed in columns 82 to 162, the third 1 is distributed in columns 163 to 243,

The last 1 is distributed in other columns.

 

Thoughts: Why can't we construct the 01 matrix like this: use five 1, the first 1 to represent the lattice sequence number, there are 81 columns, and the second 1 to represent the number. There are nine columns from 1 to 9, the third 1 indicates the row number, 9 rows, and the fourth 1 indicates that the column number also has 9, and the fifth 1 indicates the number of the nine cells, and there are also 9, so there are a total of 117 columns.

For ease of understanding, here is an example.

9, 2, 0, 0, 0, 0, 0, 0,

5, 0, 0, 0,

0, 3, 8, 0, 9, 1, 0, 0,

, 0,

0, 9, 0, 0, 0, 0, 0,

0, 7, 3, 0, 6, 4, 9, 8, 0,

, 0,

0, 0, 0, 5, 3, 0, 1,

0, 0, 0, 0, 0, 0, 7, 3

As shown in the preceding figure, there are 40 spaces and 41 known grids. We construct this Sudoku Into A 01 matrix, and the rows of the matrix are:

401 rows in 40*9 + 41

For the first number 9, in the first column of Columns 1 to 81, there are 162 columns between 82 and 9th, that is, 90 columns, and 163 columns between 243 and 9th columns, each of the 244 to 324 columns occupies 1

For the third digit 0, nine rows are selected. Therefore, when constructing the 01 matrix, nine rows are inserted into the matrix to indicate various possibilities.

Generation of sudoku

The general idea is to generate a row. The first row can be arranged in a random order of 1 to 9. In the next eight rows, each row must be sorted by dancinglink.

(1) first, randomly arrange the 9 numbers from 1 to 9, and use this arrangement as the first row of the final layout of the sudoku disk.

(2) Write a function to filter the number set that can be filled in for each grid in the next row. Line conflict is not considered during filtering.

For example

The filtering results are as follows: 123468, 123468, 135789, 135789,135789, 245679,245679, 245679

Indicates that the numbers in columns 1, 2, and 3 of the next row can be 1, 2, 3, 4, 6, or 8.

Columns 4, 5, and 6 in the next row. You can select a set of numbers, such as, and.

Columns 7, 8, and 9 in the next row. You can select a number set of 2, 4, 5, 6, and 7, 9.

In this case, when the 01 matrix is constructed, there are only two constraints.

1. For the nine grids in the next row, each lattice can only contain one number.

2. Each number in the nine grids in the next row cannot be repeated.

Because of the 3rd and 4 constraints, we have already taken into account the filtering process. We don't need to do this here.

In this case, the 01 matrix contains 9 + 9 = 18 columns, rows have 6*9 = 54 rows (6 + 6 + 6 + 6 + 6 + 6 + 6 + 6 + 6 + 6 + 6 ).

 

Application 3: Queen N

The n queen problem can also be converted to the precise coverage problem of dancinglinks.

Here we will only talk about how to convert the n queen question to the 01 matrix. There are four constraints first.

(1) All queens cannot be in the same line

(2) All queens cannot be in the same column

(3) All queens cannot be on the same left slash

(4) All queens cannot be on the same right slash

For ease of understanding, here is an example.

When n = 8, there are 8 rows, 8 columns, 15 left slashes, 15 right slashes (2 * N-1)

In this way, the matrix has 46 columns and 8x8 = 64 rows.

Each row of the matrix has four 1 rows, which are distributed in the row field, column field, left diagonal line field, and right diagonal line field respectively.

When programming to solve this problem, we need to make some modifications, because the left diagonal line field and the right diagonal line field Columns cannot be completely overwritten.

Therefore, if the row and column fields are completely overwritten, you can find a solution to the problem.

Appendix:

Dancing LInks solves the C ++ code of sudoku

# Include <iostream> # include <string. h> using namespace std; struct Node {Node * up; Node * down; Node * left; Node * right; Node * colRoot; // int row at the beginning of the column; // The row int sum; // total number of nodes in the column}; # define R 729 # define C 324 class Dlx {public: Node * nodes, * row, * col, * head; // available node, first row, first column, total header node int rowNum, colNum, nodeCount; // number of rows, number of columns, total number of nodes int * result, resultCount; // result, the number of result rows Dlx () {nodes = new Node [R * C]; // The result is that it cannot run directly using arrays, And the stack overflows, it must be placed in the heap row = new Node [R]; col = new N Ode [C + 1]; result = new int [R];} ~ Dlx () {delete [] nodes; delete [] row; delete [] col; delete [] result;} void init (int r, int c ); // initialize void cover (Node * t); // overwrite a column of void uncover (Node * t); // cancel overwriting bool solove (int k = 0 ); // search the result void addNode (int r, int c); // Add a node}; void Dlx: init (int r, int c) {int I; rowNum = r; colNum = c; // concatenate columns. col [colNum] is the total header node for (I = 0; I <= colNum; I ++) {col [I]. up = col [I]. down = col + I; col [I]. left = col + (I + colNum) % (1 + colNum); col [I]. right = col + (I + 1) % (1 + colNum); col [I]. sum = 0;} head = col + colNum; // clears the number of nodes in each row for (I = 0; I <rowNum; I ++) {row [I]. up = row [I]. down = row [I]. left = row [I]. right = row [I]. colRoot = row + I;} nodeCount = 0; // reset the total number of nodes} void Dlx: addNode (int r, int c) {nodes [nodeCount]. up = col [c]. up; nodes [nodeCount]. down = col + c; nodes [nodeCount]. left = row [r]. left; nodes [nodeCount]. right = row + r; nodes [nodeCount]. row = r; nodes [nodeCount]. colRoot = col + c; col [c]. up = col [c]. up-> down = row [R]. left = row [r]. left-> right = nodes + nodeCount ++; col [c]. sum ++;} void Dlx: cover (Node * t) {Node * p, * q; t-> left-> right = t-> right; t-> right-> left = t-> left; for (p = t-> down; p! = T; p = p-> down) {for (q = p-> right; q! = P; q = q-> right) {q-> up-> down = q-> down; q-> down-> up = q-> up; q-> colRoot-> sum -- ;}} void Dlx: uncover (Node * t) {Node * p, * q; for (p = t-> up; p! = T; p = p-> up) {for (q = p-> left; q! = P; q = q-> left) {q-> up-> down = q-> down-> up = q; q-> colRoot-> sum ++;} t-> left-> right = t-> right-> left = t;} bool Dlx: solove (int k) {// whether there are unoverwritten columns if (head-> right = head) {// record overwrites the number of rows resultCount = k; return true;} Node * pMin, * p, * q; // locate the column with the least number of nodes and overwrite for (pMin = head-> right, p = pMin-> right; p! = Head; p = p-> right) {if (pMin-> sum> p-> sum) pMin = p;} cover (pMin ); for (p = pMin-> down; p! = PMin; p = p-> down) {result [k] = p-> row; // select a node on this column, overwrite the columns of all nodes in the row where the node is located for (q = p-> right; q! = P; q = q-> right) cover (q-> colRoot); if (solove (k + 1) return true; // if the request fails, cancel overwriting for (q = p-> left; q! = P; q = q-> left) uncover (q-> colRoot);} uncover (pMin); return false;} int getRowIndex (int rowNum) {int num = rowNum % 9; int rowIndex = rowNum/81; return 81 + rowIndex * 9 + num;} int getColIndex (int rowNum) {int num = rowNum % 9; int index = rowNum/9; // The position int colIndex = index % 9; return 162 + colIndex * 9 + num;} int getSquareIndex (int rowNum) {int num = rowNum % 9; int index = rowNum/9; // The position int rowIndex = index/9; int colIndex = index % 9; int squareIndex = int (rowIndex/3) * 3 + colIndex/3; return 243 + squareIndex * 9 + num;} int main3 () {int I, j; int node4 = 0; char str [82]; Dlx dlx; // cin> n; dlx. init (729,324); // for (I = 0; I <9; I ++) // {// cin> (str + I * 9 ); //}//...... 52 .. 8. 4 ...... 3... 9... 5. 1... 6 .. 2 .. 7 ........ 3 ..... 6... 1 .......... 7. 4 ....... 3. const char * input = ". 2738 .. 1 .. 1... 6735 ....... 293.20.2.8 ........... 6.1745.364 ....... 9518... 7 .. 8 .. 6534. "; strcpy (str, input); for (I = 0; I <729; I ++) {// cout <"row =>" <I <"\ tcol => location" <I/9 <"\ t" <81 + I /9/9*9 + I % 9 <"\ t column" <162 + I/9% 9*9 + I % 9 <"\ t block" <243 + (I/9/9/3*3 + I/9% 9/3) * 9 + I % 9; // cout <"row =>" <I <"\ tcol => location" <I/9 <"\ t row" <getRowIndex (I) <"\ t column" <getColIndex (I) <"\ t block" <getSquareIndex (I); if (str [I/9] = '. '| str [I/9]-'1' = I % 9) {node4 ++; int rowIndex = I; int colIndex = I/9; dlx. addNode (rowIndex, colIndex); // location conflict dlx. addNode (rowIndex, getRowIndex (I); // line conflict dlx. addNode (rowIndex, getColIndex (I); // column conflict dlx. addNode (rowIndex, getSquareIndex (I); // block conflict // cout <"\ t <=" ;}// cout <endl;} if (dlx. solove () {// The result is saved to the string for (I = 0; I <81; I ++) {j = dlx. result [I]; str [j/9] = '1' + j % 9;} // output string for (I = 0; I <9; I ++) {for (j = 0; j <9; j ++) cout <str [I * 9 + j]; cout <endl ;}} return 0 ;}

Attachment to generate the Flex code for the final layout of the sudoku Disk

<? Xml version = "1.0" encoding = "UTF-8"?> <S: Drawing wedapplication xmlns: fx = "http://ns.adobe.com/mxml/2009" xmlns: s = "library: // ns.adobe.com/flex/spark" xmlns: mx = "library: // ns.adobe.com/flex/mx"> <fx: declarations> <! -- Place non-visual elements (e.g., services, value objects) here --> </fx: Declarations> <fx: Script> <! [CDATA [import model. dancingNode; private var sample: String = "1279,2367, 1369,24789, 4578,259,134 58,1368, 456"; private var rowArr: Array = []; private var colArr: Array = []; private var head: DancingNode; private var nodes: Array = []; private var cnt: Array = []; private var answer: Array = []; private var answerArr: array = []; private function _ init (restrict: String): void {answerArr = []; answer = []; cnt = []; nodes = []; rowArr = []; colArr = []; Var I: int; var colLen: int = 18; var rowLen: int = restrict. split (','). join (''). length; for (I = 0; I <rowLen; I ++) {var row: DancingNode = new DancingNode (I); rowArr. push (row) ;}for (I = 0; I <= colLen; I ++) {var col: DancingNode = new DancingNode (-1, I); colArr. push (col); cnt. push (0);} var colArrLen: int = colArr. length; for (I = 0; I <colArr. length; I ++) {var left: int = (I + colArrLen-1) % colArrLen; var right: int = (I + 1) % colArrLen; Dan CingNode (colArr [I]). left = colArr [left]; DancingNode (colArr [I]). right = colArr [right];} head = colArr [0]; // create linksvar rowIndex: int = 0; var arr1: Array = restrict. split (','); for (I = 0; I <arr1.length; I ++) {var arr2: Array = String (arr1 [I]). split (''); for (var j: int = 0; j <arr2.length; j ++) {var colIndex1: int = I + 1; var colIndex2: int = 9 + int (arr2 [j]); addNode (rowIndex, colIndex1, I, int (arr2 [j]); addNode (rowIndex, colIndex2, I, Int (arr2 [j]); rowIndex ++ ;}for (I = 0; I <rowLen; I ++) {DancingNode (rowArr [I]). left. right = DancingNode (rowArr [I]). right; DancingNode (rowArr [I]). right. left = DancingNode (rowArr [I]). left ;}} private function addNode (r: int, c: int, r1: int, c1: int): void {var node: DancingNode = new DancingNode (r, c ); node. rowValue = r1; node. colValue = c1; node. up = colArr [c]. up; node. down = colArr [c]; node. left = rowArr [r]. left; node. right = row Arr [r]; cnt [c] ++; colArr [c]. up = colArr [c]. up. down = rowArr [r]. left = rowArr [r]. left. right = node; nodes. push (node);} private function remove (node: DancingNode): void {// trace ("remove =>", node. col); node. left. right = node. right; node. right. left = node. left; for (var p: DancingNode = node. down; p! = Node; p = p. down) {for (var q: DancingNode = p. right; q! = P; q = q. right) {q. up. down = q. down; q. down. up = q. up; cnt [q. col] -- ;}} private function resume (node: DancingNode): void {// trace ("resume =>", node. col); for (var p: DancingNode = node. down; p! = Node; p = p. down) {for (var q: DancingNode = p. right; q! = P; q = q. right) {q. up. down = q; q. down. up = q; cnt [q. col] ++;} node. left. right = node; node. right. left = node;} private function dancing (depth: int): Boolean {// whether there are columns not overwritten if (head. right = head) {var arr: Array = []; for (var I: int = 0; I <answer. length; I ++) {var node: DancingNode = answer [I]; arr [node. rowValue] = node. colValue;} answerArr. push (arr); return true;} var pMin: DancingNode; var p: DancingNode; // locate the column with the least number of nodes and overwrite for (pMin = head. righ T, p = pMin. right; p! = Head; p = p. right) {if (cnt [pMin. col]> cnt [p. col]) {pMin = p ;}} remove (pMin); var q: DancingNode; for (p = pMin. down; p! = PMin; p = p. down) {// select a node on this column and overwrite answer [depth] = p; for (q = p. right; q! = P; q = q. right) {remove (colArr [q. col]);} if (dancing (depth + 1) {if (answerArr. length> 10) {return true ;}}for (q = p. left; q! = P; q = q. left) {resume (colArr [q. col]) ;}} resume (pMin); if (answerArr. length> 0) {return true;} return false;} private function getSudokuLine (restricts: Array): Array {var arr: Array = []; for (var I: int = 0; I <restricts. length; I ++) {arr. push (restricts [I] as Array ). join ('');} _ init (arr. join (','); if (dancing (0) {var line: Array = answerArr [int (answerArr. length * Math. random ()]; trace ('getsudokuline, answer length => ', answer Arr. length); return line;} return [];} // obtain the random arrangement of 1 to 9. private function getRandomArr (value: int): Array {var bak: array = []; for (var I: int = 1; I <= value; I ++) {bak. push (I);} var randLine: Array = []; while (bak. length> 0) {var index: int = bak. length * Math. random (); randLine. push (bak [index]); bak. splice (index, 1) ;}return randLine;} public function createFullSudoku (): Array {var sudokuArr: Array = []; while (sudokuArr. length <9) {sud OkuArr = []; sudokuArr. push (getRandomArr (9); for (var I: int = 0; I <8; I ++) {var restricts: Array = getRestricts (sudokuArr); if (restricts. length = 0) {break;} var line: Array = getSudokuLine (restricts); if (line. length = 0) {break;} sudokuArr. push (line) ;}return sudokuArr;} private function getRestricts (curLayout: Array): Array {var I: int; var ret: Array = []; for (I = 0; I <9; I ++) {var arr: Array = getCandidateNums (curLayout, I); if (arr. Length = 0) {return [];} ret. push (arr) ;}return ret ;}// according to the current layout, obtain the list of candidates for the index column. private function getCandidateNums (curLayout: Array, index: int ): array {var I: int; var line: Array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; if (curLayout. length = 0) {return [1, 3, 4, 5, 6, 7, 8, 9];} // column exclusion for (I = 0; I <curLayout. length; I ++) {line [curLayout [I] [index] = 0;} // exclude var col3_3: int = index/3; var row3_3: int = curLayout. length/3; var inRow3_3: int = CurLayout. length % 3; for (I = row3_3 * 3; I <row3_3*3 + inRow3_3; I ++) {line [curLayout [I] [col3_3 * 3] = 0; line [curLayout [I] [col3_3*3 + 1] = 0; line [curLayout [I] [col3_3*3 + 2] = 0;} var ret: array = []; for (I = 0; I <line. length; I ++) {if (line [I]! = 0) {ret. push (I) ;}return ret;} private function createSudoku (): void {var arr: Array = createFullSudoku (); var arr2: Array = []; for (var I: int = 0; I <arr. length; I ++) {arr2.push (arr [I] as Array ). join (',');} area. text = arr2.join ('\ n');}]> </fx: Script> <s: VGroup horizontalCenter = "0" verticalCenter = "0"> <s: textArea width = "300" height = "300" id = "area"/> <s: Button label = "get full sudoku" click = "createSudoku () "/> </s: VGroup> </s: WindowedApplication>

package model{public class DancingNode{public var row:int;public var col:int;public var rowValue:int;public var colValue:int;public var up:DancingNode;public var down:DancingNode;public var left:DancingNode;public var right:DancingNode;public function DancingNode(r:int=-1,c:int=-1){row = r;col = c;up = this;down = this;left = this;right = this;}}}

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.