说说:
这道题目类似于八皇后问题。有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(八皇后问题变形)
原文地址:http://blog.csdn.net/u011915301/article/details/39720803