在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1
21
解题思路: 该题需要用到回溯法,搜索的时候用逐行深搜,其实跟八皇后为题类似,题目中也给出(数据保证不出现多余的空白行或者空白列),所以逐行深搜判断列有无重复即可。 难点是在每一行有两种情况,一是放棋子,这时候需要回溯,因为一行可能出现多个位置可以放。二是不放棋子,因为可能棋子数会比位置少,所以不放棋子的时候可以直 接递归。#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int vis[10],n,k,sum; char s[10][10]; void dfs(int x,int y) //逐行搜索,x行,y列 { if(y==k) //棋盘摆放完成 { sum++; return ; } if(x>=n)return ; for(int i=0; i<n; i++) //判断每一列是否被放旗子 { if(vis[i]==0&&s[x][i]=='#') { vis[i]=1; dfs(x+1,y+1); vis[i]=0;//回溯后,说明摆好棋子的状态已记录,当前的列标记还原 } } dfs(x+1,y);//这里是难点,当K<n时,x在等于n之前就可能已经把全部棋子摆好 //又由于当全部棋子都摆放好的某个期盼状态已经在前面循环时记录了 //因次为了处理多余行,另当前位置先不摆棋子,搜索下一行放旗子的情况 } int main() { int i,j; while(~scanf("%d%d",&n,&k)) { if(n==-1&&k==-1)break; memset(vis,0,sizeof(vis)); for(i=0; i<n; i++) scanf("%s",s[i]); sum=0; dfs(0,0); printf("%d\n",sum); } return 0; }