检查所有可能值的递归方法(C)

时间:2014-12-05 20:22:05

标签: c arrays recursion

我正在编写一个读取整数值(n)的程序,并创建一个包含这些维度(nXn)的国际象棋桌。然后,我必须看看是否有一种方法可以将n个皇后放置在这个板上,使得它们中没有一个可以相互攻击(对于那些不熟悉国际象棋的人,皇后区可以攻击同一列中的任何一块或者排成它们,以及任何穿过女王的对角线上的那块。这些值存储在一个数组(int board [n])中,最初设置为全-1。 board [0]中的值对应于第0列中的queen位于的行。最初,所有值都设置为-1,这意味着所述行中没有任何部分。

我正在尝试找到一种方法,我可以通过一种方法检查是否可以传递每个可能的坐标集(基本上每个可能的长度为n的数组,其值可以在0到n-1之间)这是布置碎片的有效方法,如果布局有效,它必须将该数组传递给可视化它的方法,如下所示:

* * Q *
Q * * *
* * * Q
* Q * *

检查和输出的方法已设置并正常工作,我只需要弄清楚如何生成存储该坐标的数组的所有可能排列。

编辑: 这是迄今为止的代码(12月6日下午2点更新):

#include <stdio.h>
#include <stdlib.h>
int permutations (int board[],int n, int counter, int index);
int check (int board[], int n);
int printout (int board[], int n, int isValid);
int main() {
  int n, board[n];
  while (1==scanf("%d", &n) && n > 0) {
      int board[] = {-1};
      int isValid = permutations(board,n, 0, 0); 
      printout(board, n, isValid);
}
  return 0;
}
int permutations(int board[],int n, int counter, int index){
board[index] = counter;
int max = n-1;
if ((check(board, n) == 1) && (index == max)){
return 1;
}
if (check(board, n) == 1){
permutations(board, n, 0, ++index);
}
else if (check(board, n) == 0){
counter++;
}
if (counter == n){
return 0;
}  
}
int check(int board[], int n){
int i,j;
int isValid = 1;
for (i=0; i<n && isValid; ++i) {
      if (board[i]==-1) continue;
      for (j=i+1; j<n && isValid; ++j) {
    if (board[j]==-1) continue;
    if ( board[i] == board[j] ||
             board[i]-board[j] == i-j ||
             board[i]-board[j] == j-i )
      isValid = 0;
      }
    }
return isValid;}
int printout(int board[], int n, int isValid){
int i,j;
    putchar('\n');
    for (i=n-1; i>=0; --i) {
      for (j=0; j<n; ++j) {
    if (j>0) putchar(' ');
    putchar( board[j]==i ? 'Q' : '.' );
      }
      putchar('\n');
    }
    puts( isValid ? "valid configuration" : "invalid configuration" );
    return 0;
    }

3 个答案:

答案 0 :(得分:0)

提示你的作业(递归):

从空白板开始,然后调用递归例程。在棋盘上迭代,试图把一个女王放在上面。如果受到攻击则继续。否则请用电路板打电话给自己(现在还有一个女王)。在棋盘上迭代,试图把一个女王放在上面。如果受到攻击则继续。请自己打电话......

如果你已经达到6个皇后,则返回“成功”并展开递归。

如果在任何时候你不能在棋盘上放置另一个女王,请返回“失败”,移除女王并继续你自己所在地的迭代。

这是一种“蛮力”的方法。

答案 1 :(得分:0)

此代码有效(这是您的作业):

int checkBoard(int board[8][8]);
int putQueens(int board[8][8], int nQueens);
void printBoard(int board[8][8]);

int eightQueens(void)
{
    int board[8][8];
    memset(board, 0, sizeof(int)*64);
    if (putQueens(board, 0)) {
        printBoard(board);
        return (1);
    }
    return(0);
}
int putQueens(int board[8][8], int nQueens)
{
    int i, j;
    for (i=0; i<8; i++) {
        for (j=0; j<8; j++) {
            if (board[i][j]==0) {
                board[i][j]= 1;
                if (checkBoard(board)) {
                    if (nQueens==7) return(1);
                    if (putQueens(board, nQueens+1)) return(1);
                }
                board[i][j]= 0;
            }
        }
    }
    return(0);
}
int checkBoard(int board[8][8])
{
    int i, j;
    for (i=0; i<8; i++) {
        for (j=0; j<8; j++) {
            if (board[i][j]) {
                int ii, jj;
                for (ii=i+1; ii<8; ii++) {
                    if (board[ii][j]) return(0);
                }
                for (jj=j+1; jj<8; jj++) {
                    if (board[i][jj]) return(0);
                }
                for (ii=i+1, jj=j+1; ii<8 && jj<8; ii++, jj++) {
                    if (board[ii][jj]) return(0);
                }
                for (ii=i-1, jj=j-1; ii>0 && jj>0; ii--, jj--) {
                    if (board[ii][jj]) return(0);
                }
                for (ii=i-1, jj=j+1; ii>0 && jj<8; ii--, jj++) {
                    if (board[ii][jj]) return(0);
                }
                for (ii=i+1, jj=j-1; ii<8 && jj>0; ii++, jj--) {
                    if (board[ii][jj]) return(0);
                }
            }
        }
    }
    return (1);
}

我对checkBoard不满意;它可以变得更优雅。 (你的作业)。

所以你已经学会了:请发表评论,解释你的代码出错的地方以及你从上面的代码中学到了什么。

答案 2 :(得分:0)

main()中的边际错误:在输入board[n]之前,不要定义变量长度数组n。 现在算法:对于分配的任务(在棋盘上放置n个皇后),生成包含少于n个皇后的布局是没有意义的。因此,使用可能重新排列为有效布局的一些排列初始化board;我在下面选择了{ 0, 1, 2 .. n-1 }。我重写了函数permutations(),希望生成数组的所有可能的排列 board[],如果有一个有效的布局,...传递数组到一个可视化它的方法(您的原始printout())。此外,该函数为有效布局增加了一个计数器 - 我发现计数因n的不同值而有所不同。

int n, counter; // counter: counts valid layouts found

void permutations(int board[], int j)
{   // generate all possible permutations of board[0..j-1]
    int i = --j;
    if (i <= 0)
    {   // arrived at one permutation - check it, and print if valid
        if (check(board, n)) ++counter, printout(board, n, 1);
        return;
    }

    permutations(board, i);
    while (i--)
    {
        int k, x;
        for (k = j; k > i; --k)
            if (board[i] == board[k]) break;
        if (k > i) continue;

        x = board[i], board[i] = board[j], board[j] = x;
        permutations(board, j);
        x = board[i], board[i] = board[j], board[j] = x;
    }
}

int main()
{
    while (1==scanf("%d", &n) && n > 0)
    {
        int board[n], i;
        for (i = 0; i < n; ++i) board[i] = i;
        counter = 0, permutations(board, n); 
        printf("%d valid configurations\n", counter);
    }
    return 0;
}
相关问题