说说:
这道题目类似于八皇后问题。有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