Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用舞蹈链接的精确封面_C++_Algorithm_Knuth - Fatal编程技术网

C++ 使用舞蹈链接的精确封面

C++ 使用舞蹈链接的精确封面,c++,algorithm,knuth,C++,Algorithm,Knuth,在经历了这些之后,我试图实现舞蹈链接来解决确切的封面问题,下面是从中提取并修改的代码(这是列-行结构,我需要行-列结构)。它工作得很好,只是在搜索函数中,它从未到达成功的终止块。我尝试跟踪,发现 RowNode = Column->Down ; RowNode!=Column ; RowNode = RowNode->Down 是谁造成的。示例:对于以下矩阵 1 2 3 4 1 1 x x x 1 1 x x x 1 1 我的代码未能覆盖标题为4的最后一列 我怎样才能克服这个问题

在经历了这些之后,我试图实现舞蹈链接来解决确切的封面问题,下面是从中提取并修改的代码(这是列-行结构,我需要行-列结构)。它工作得很好,只是在
搜索
函数中,它从未到达成功的终止块。我尝试跟踪,发现

RowNode = Column->Down ; RowNode!=Column ; RowNode = RowNode->Down
是谁造成的。示例:对于以下矩阵

1 2 3 4
1 1 x x
x 1 1 x
x x 1 1
我的代码未能
覆盖
标题为4的最后一列

我怎样才能克服这个问题?这是完整的代码

#include <iostream>
#include <vector>
#include <cstdio>
#include <stdbool.h>

#define MAX_ROW 50L
#define MAX_COL 100L

using namespace std;

struct str_node {
    struct str_node * Header;
    struct str_node * Left;
    struct str_node * Right;
    struct str_node * Up;
    struct str_node * Down;
    int HeaderID,RowIndex,ColIndex;
};


int nCol;
int nRow;
struct str_node Matrix[MAX_ROW][MAX_COL];
vector<struct str_node*>ResultRow;
struct str_node Root;
struct str_node *RootNode = &Root;
bool Data[MAX_ROW][MAX_COL];
int maxResult;

//functions to get the neighbours (are circular)
inline int dataLeft(int i) { return (i-1 < 0) ? nCol-1 : i-1 ; }
inline int dataRight(int i) { return (i+1) % nCol ; }
inline int dataUp(int i) { return (i-1 < 0) ? nRow-1 : i-1 ; }
inline int dataDown(int i) { return (i+1) % nRow ; }

void CreateToroidalMatrix(void) {

    int a,b, i, j;

    for(a = 0 ; a <= nRow ; a++) {

        for(b=0 ; b < nCol ; b++) {

            if(Data[a][b]) {

                Matrix[a][b].RowIndex = a;
                Matrix[a][b].ColIndex = b;

                // Left pointer
                i = a; j = b; do {j = dataLeft(j); } while (!Data[i][j]);
                Matrix[a][b].Left = &Matrix[i][j];

                // Right pointer
                i = a; j = b; do {j = dataRight(j); } while (!Data[i][j]);
                Matrix[a][b].Right = &Matrix[i][j];

                // Up pointer
                i = a; j = b; do {i = dataUp(i); } while (!Data[i][j]);
                Matrix[a][b].Up = &Matrix[i][j];

                // Down pointer
                i = a; j = b; do {i = dataDown(i); } while (!Data[i][j]);
                Matrix[a][b].Down = &Matrix[i][j];

                //Head pointer
                Matrix[a][b].Header = &Matrix[0][b];
                Matrix[a][b].HeaderID = b+1;

            }
        }
    }

    //Initialize root
    RootNode->Right = &Matrix[0][0];
    RootNode->Left = &Matrix[0][nCol-1];
    Matrix[0][0].Left = RootNode;
    Matrix[0][nCol-1].Right = RootNode;
}

void Cover(struct str_node *ColNode){

    cout<<"Covering header node "<<ColNode->HeaderID<<'\n';

    struct str_node *RowNode, *RightNode;

    ColNode->Right->Left = ColNode->Left;
    ColNode->Left->Right = ColNode->Right;

    for(RowNode = ColNode->Down ; RowNode!=ColNode ; RowNode = RowNode->Down) {
        for(RightNode = RowNode->Right ; RightNode!=RowNode ; RightNode = RightNode->Right) {
            RightNode->Up->Down = RightNode->Down;
            RightNode->Down->Up = RightNode->Up;
        }
    }
}

void UnCover(struct str_node *ColNode) {
    //uncover the covered nodes to find a different solution
    struct str_node *RowNode, *LeftNode;

    for(RowNode = ColNode->Up; RowNode!=ColNode; RowNode = RowNode->Up) {
        for(LeftNode = RowNode->Left; LeftNode!=RowNode; LeftNode = LeftNode->Left) {
            LeftNode->Up->Down = LeftNode;
            LeftNode->Down->Up = LeftNode;
        }
    }
    ColNode->Right->Left = ColNode;
    ColNode->Left->Right = ColNode;
}

void Search(int k){

    //all columns covered

    if( RootNode->Right == RootNode){
        cout<<"found\n";
        if(maxResult < k)
            maxResult = k;
        return;
    }

    //if not covered
    else{

        struct str_node *Column = RootNode->Right;
        struct str_node *RowNode;
        struct str_node *RightNode;
        struct str_node *LeftNode;

        Cover(Column);

        for( RowNode = Column->Down ; RowNode!=Column ; RowNode = RowNode->Down){

            ResultRow.push_back(RowNode);

            for(RightNode = RowNode->Right; RightNode!=RowNode; RightNode = RightNode->Right)
                Cover(RightNode->Header);

            Search(k+1);
            RowNode = ResultRow.back();
            ResultRow.pop_back();
            Column = RowNode->Header;

            for(LeftNode = RowNode->Left; LeftNode!=RowNode; LeftNode = LeftNode->Left)
                UnCover(LeftNode->Header);
        }
        UnCover(Column);
    }
}

void GetData(void){
    int pos,k;
    scanf("%d%d",&nCol, &nRow);

    for(int i=0 ; i<nCol ; i++)
        Data[0][i] = true;

    for(int i=1 ; i<=nRow ; i++){
        scanf("%d",&k);
        for(int j=0 ; j<k ; j++){
            scanf("%d",&pos);
            Data[i][pos-1] = true;
        }
    }
    CreateToroidalMatrix();
}

int main(void){
    GetData();
    Search(0); // from level 0
    printf("%d\n",maxResult+1);
    return 0;
}
#包括
#包括
#包括
#包括
#定义最大行50L
#定义最大列100L
使用名称空间std;
结构str_节点{
结构str_节点*头;
结构str_节点*左;
结构str_节点*右侧;
结构str_节点*Up;
结构str_节点*向下;
int HeaderID、ROWDINDEX、ColIndex;
};
int nCol;
int nRow;
结构str_节点矩阵[MAX_ROW][MAX_COL];
vectorResultRow;
结构str_节点根;
struct str_node*RootNode=&Root;
布尔数据[最大行][最大列];
int-maxResult;
//获取邻居的函数(是循环函数)
内联int-dataLeft(inti){return(i-1<0)?nCol-1:i-1;}
内联int-dataRight(inti){return(i+1)%nCol;}
内联int-dataUp(inti){return(i-1<0)?nRow-1:i-1;}
内联int-dataDown(inti){return(i+1)%nRow;}
void CreateToroidalMatrix(void){
int a,b,i,j;
对于(a=0;a右=&矩阵[0][0];
RootNode->Left=&矩阵[0][nCol-1];
矩阵[0][0]。左=根节点;
矩阵[0][nCol-1]。右=根节点;
}
空洞覆盖(结构str_节点*ColNode){
coutRight=ColNode->Right;
对于(RowNode=ColNode->Down;RowNode!=ColNode;RowNode=RowNode->Down){
对于(RightNode=RowNode->Right;RightNode!=RowNode;RightNode=RightNode->Right){
右节点->向上->向下=右节点->向下;
右节点->向下->向上=右节点->向上;
}
}
}
void discover(结构str_节点*ColNode){
//揭开覆盖的节点以找到不同的解决方案
结构str_节点*RowNode,*LeftNode;
对于(RowNode=ColNode->Up;RowNode!=ColNode;RowNode=RowNode->Up){
对于(LeftNode=RowNode->Left;LeftNode!=RowNode;LeftNode=LeftNode->Left){
LeftNode->Up->Down=LeftNode;
LeftNode->Down->Up=LeftNode;
}
}
ColNode->Right->Left=ColNode;
ColNode->Left->Right=ColNode;
}
无效搜索(INTK){
//所有栏目都包括在内
if(RootNode->Right==RootNode){
coutDown;RowNode!=列;RowNode=RowNode->Down){
ResultRow.push_back(行节点);
对于(RightNode=RowNode->Right;RightNode!=RowNode;RightNode=RightNode->Right)
封面(右节点->标题);
搜索(k+1);
RowNode=ResultRow.back();
ResultRow.pop_back();
列=行节点->标题;
对于(LeftNode=RowNode->Left;LeftNode!=RowNode;LeftNode=LeftNode->Left)
揭开(左节点->标题);
}
揭(柱);
}
}
void GetData(void){
int pos,k;
scanf(“%d%d”,&nCol,&nRow);

对于(inti=0;iOk),我再次检查了源代码并找到了bug,忘记了在
GetData(void)中增加
nRow
。这些小错误让人毛骨悚然!下面是代码的修改部分,现在它工作得很好。
nRow
必须增加一次,因为我为每列的
标题使用了一个额外的行

void GetData(void){
    int pos,k;
    scanf("%d%d",&nCol, &nRow);

    nRow++;//this is the change

    for(int i=0 ; i<nCol ; i++)
        Data[0][i] = true;

    for(int i=1 ; i<nRow ; i++){
        scanf("%d",&k);
        for(int j=0 ; j<k ; j++){
            scanf("%d",&pos);
            Data[i][pos-1] = true;
        }
    }
    CreateToroidalMatrix();
}

因为nRow比它应该的小一个,所以内联函数用于获取邻居,特别是
dataUp()
dataDown()
返回了意外的值。

我不能肯定,但是因为你修改了矩阵的结构,你可能打破了
的封面
揭开
函数。谢谢你,这看起来像是一个很酷的博客。我看到许多其他数独的实现几乎都有相同的代码,然后当我翻阅Donald Knuth的原始论文时,我发现这一切都是从那里开始的:D@AndyG
封面
揭开
都很好:)
for(a=0 ; a<nRow ; a++) // removed equal sign