首页 > 代码库 > Don't Get Rooked UVA 639(八皇后问题变形)

Don't Get Rooked UVA 639(八皇后问题变形)

说说:

这道题目类似于八皇后问题。有n*n的正方形棋盘,且n<=4。例如在n=4时,有下图所示的棋盘,其中每两个棋子不能放在同一行或者同一列,除非有围墙(黑色的格子)将它们隔开。求给定的棋盘,能放下的最多的棋子数目。


分析:

在八皇后问题中,我们对整个棋盘分成八行考虑的,每行插入一个棋子。所以对于这道题目解决方案也类似,同样是一行一行插入。但是与八皇后问题不同的是,本题中棋盘一行可能插入多个棋子,也可能没有棋子。所以在递归函数中,不仅要给出所要处理的行的信息,也要给出所要处理的列的信息,其实就是个准确的坐标。然后在本行中找第一个可能插入棋子的空白段,用start,end标记边界,类似于八皇后问题递归回溯处理,并在递归时,将当前函数的end作为下一层函数的start,并且和八皇后问题不同的是,无论空白段中能不能插入棋子,都要进行递归,差别不过是当前已经放好的棋子数目不同而已。若本行中没有空白格了,则直接进入下一行查找。当行数大于给定的n时,递归结束。具体操作,请参见下面附上的源代码。

源代码:

#include <stdio.h>
#define MAX 4+3

char board[MAX][MAX];
int n,max;

void search(int,int,int);
int main(){
 int i;
// freopen("data","r",stdin);
 while(scanf("%d",&n)){
  if(!n)
    break;

  for(i=0;i<n;i++)
    scanf("%s",board[i]);
  max=0;
  search(0,0,0);
  printf("%d\n",max);
 }

 return 0;
}

void search(int row,int col,int rook){
  int start,end,i,test,sign,j;
  if(row>=n){//递归结束
    max=rook>max?rook:max;
    return ;
  }

  start=col;
  while(start<n&&board[row][start]=='X')
    start++;

  if(start>=n)//若本行没有空白段,直接进入下一行
    search(row+1,0,rook);
  else{
   end=start;
   while(end<n&&board[row][end]=='.')//end位于空白段结尾的后一位置
    end++;
  for(i=start;i<end;i++){
    test=row-1;
    sign=1;
    while(test>=0&&board[test][i]!='X'){//测试当前列能否放棋子
     if(board[test][i]=='*')
       sign=0;
     test--;
    }

    if(sign){
      board[row][i]='*';
      search(row,end,rook+1);
      board[row][i]='.';//注意回溯
    }
    else
      search(row,end,rook);//不论当前空白段放没放棋子,都要递归
  }
 }

 return;
}


Don't Get Rooked UVA 639(八皇后问题变形)