在NxN棋盘上N个皇后

时间:2015-03-21 16:53:12

标签: c

#include <stdio.h>
#include <math.h>

int n=4;
int GetQueenSettings(int board[4][4],int currentRow,int n)
{
    //decide when the recursion stops
    if(currentRow==n)
        return 1; //successful setting
    //otherwise we set column by column in this row and continue
    int TotalSettingCount=0;
    for(int i=0;i<n;i++)
    {
        //make sure it can be set (it is unset at that moment)
        if(board[currentRow][i]==0)
        {
            board[currentRow][i]==1+currentRow;
            //use row related info for settings
            //now set invalid positions for remaining rows
            setInvalid(board,currentRow,n,i);
            //recover after this before trying the next
            TotalSettingCount += GetQueenSettings(board,currentRow+1,n);
            board[currentRow][i]=0;
            RecoverBoard(board,currentRow,n);
        }
    }
    return TotalSettingCount;
}

void setInvalid(int board[4][4],int currentRow,int n,int i)
{
    //vertical and diagonal elements
    for(int row=currentRow+1;row<n;row++) //start from the next line
    {
        //firstly make sure board can be set
        if(board[row][i]==0)//vertical position
            board[row][i]=-(1+currentRow);
        //now check diagonal
        int rowGap=row-currentRow;
        if(i-rowGap>=0 && board[row][i-rowGap]==0)
        {
            //left bottom diagonal position
            board[row][i-rowGap]=-(1+currentRow);
        }
        if(i+rowGap<n && board[row][i+rowGap]==0)
        {
            //bottom right diagonal position
            board[row][i+rowGap]=-(1+currentRow);
        }

    }
}

void RecoverBoard(int board[4][4],int currentRow,int n)
{
    //recover is to check all remaining rows if index is higher than current row(setters)
    //OR less than -currentRow(invalids)!
    for(int row=currentRow+1;row<n;row++)
    {
        for(int col=0;col<n;col++)
        {
            if(board[row][col]>currentRow || board[row][col]< -currentRow)
                board[row][col]=0;
        }
    }
}
int main()
{

    int board[n][n];
    printf("Number of settings:-> %d",GetQueenSettings(board,0,n));

    return 0;
}

在NxN棋盘上放置N个队列而不会相互干扰。当我运行此代码时,我得到的答案为零而不是2。我还想办法把阵列板传递给可变大小的函数(大小将由用户给出)。我做错了什么?!

3 个答案:

答案 0 :(得分:0)

很久以前我开发了一个类似于你的算法的算法,也许它可以帮助你。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

long Solutions;

void AllocBoard(int *** Board, int Queens)
    {
    int i;

    *Board = (int **)malloc(sizeof(int *) * Queens);

    for(i = 0; i < Queens; i++)
        {
        (*Board)[i] = (int *)malloc(sizeof(int) * Queens);
        memset((*Board)[i], 0, sizeof(int) * Queens);
        }
    }

void DeallocBoard(int *** Board, int Queens)
    {
    int i;

    for(i = 0; i < Queens; i++)
        free((*Board)[i]);

    free(*Board);
    }

void SavePosition(int *** Board, int Queens, int Col, int Row, int Inc)
    {
    int i, j;

    for(i = 0; i < Queens; i++)
        {
        if((*Board)[Col][i] >= 0) (*Board)[Col][i] += Inc;
        if((*Board)[i][Row] >= 0) (*Board)[i][Row] += Inc;
        }

    for(i = Col, j = Row; j < Queens && i < Queens; i++, j++)
        if((*Board)[i][j] >= 0) (*Board)[i][j] += Inc;

    for(i = Col, j = Row; j >= 0 && i >= Col; i--, j--)
        if((*Board)[i][j] >= 0) (*Board)[Col][j] += Inc;

    for(i = Col, j = Row; j >= 0 && i < Queens; i++, j--)
        if((*Board)[i][j] >= 0) (*Board)[i][j] += Inc;

    for(i = Col, j = Row; j < Queens && i >= Col; i--, j++)
        if((*Board)[i][j] >= 0) (*Board)[i][j] += Inc;
    }

void FindSolutions(int *** Board, int Queens, int Col)
    {
    int i, j;

    for(i = 0; i < Queens; i++)
        {
        if((*Board)[Col][i] != 0) continue;

        (*Board)[Col][i] = -1;
        if(Col + 1 == Queens)
            Solutions++;
        else
            {
            SavePosition(Board, Queens, Col, i, 1);
            FindSolutions(Board, Queens, Col + 1);
            SavePosition(Board, Queens, Col, i, -1);
            }

        (*Board)[Col][i] = 0;
        }
    }

void main(int argc, char **argv)
    {
    int Queens, ** Board = NULL;
    clock_t Start, End;

    clrscr();
    if(argc < 2)
        Queens = 8;
    else
        Queens = atoi(argv[1]);

    Solutions = 0;

    Start = clock();
    AllocBoard(&Board, Queens);
    FindSolutions(&Board, Queens, 0);
    DeallocBoard(&Board, Queens);
    End = clock();

    printf("Solutions %ld\n", Solutions);
    printf("Estimated time: %f", (End - Start) / CLK_TCK);
    getch();
    }

希望这有帮助

答案 1 :(得分:0)

询问关于简短程序的“为什么它不起作用”并不是很好。尝试使用任何调试器自行调试,或者只在每个步骤的重要位置使用打印。实际上,C没有数组,而是有指针。您可以非常相似地使用它们,这就是为什么您需要将int board[4][4]更改为int **board并添加一个参数:int N(单元格数),这就是全部。不应更改所有其他代码。

答案 2 :(得分:0)

您应初始化board。您可以从充满垃圾值的电路板开始。您使用可变长度数组作为电路板。此类数组无法初始化,因此您必须使用循环或memset中的<string.h>将电路板设置为全零:

int board[n][n];

memset(board, 0, sizeof(board));

当维度作为先前的参数传入时,您可以将可变长度数组传递给函数,例如:

int GetQueenSettings(int n, int board[n][n], int currentRow) { ... }

同时修复=中的== / setInvalid开关:

    if (board[row][i] == 0)
        board[row][i] = -(1 + currentRow);

最后确保所有函数在调用时都有适当的原型。