DFS,没想法就很难很难,有想法就很容易的题
棋盘规则与否不是难点,无论规则不规则都可以用标记去解决
难点在于 棋盘的行数(列数)n 与 待摆放的棋子总数k 的关系为k<=n
K==n时还是比较好办的
K<n时就让人有点迷糊不知怎样处理了
/*
* POJ_1321.cpp
*
* Created on: 2013年12月17日
* Author: Administrator
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 10;
bool mp[maxn][maxn];
bool vis_col[maxn];//列标记
int n,k;
int status;//方案数
void dfs(int row,int num){//逐行搜索,row为当前搜索行,num为已填充的棋子数
if(num == k){
status++;
return ;
}
if(row > n){//配合下面DFS(row+1,num); 语句使用,避免搜索越界
return ;
}
int j;
for(j = 1 ; j <= n ; ++j){
if(mp[row][j] && vis_col[j] == false){
vis_col[j] = true;//放置棋子的列标记
dfs(row+1,num+1);
vis_col[j] = false;//回溯后,说明摆好棋子的状态已记录,当前的列标记还原
}
}
/**
* 这里是难点,当k<n时,row在等于n之前就可能已经把全部棋子放好
又由于当全部棋子都放好后的某个棋盘状态已经在前面循环时记录了
因此为了处理多余行,令当前位置先不放棋子,搜索在下一行放棋子的情况
*/
dfs(row+1,num);
}
int main(){
while(scanf("%d%d",&n,&k)!=EOF,n != -1){
memset(mp,false,sizeof(mp));
memset(vis_col,false,sizeof(vis_col));
status = 0;
int i,j;
for(i = 1 ; i <= n ; ++i){
for(j = 1 ; j <= n ; ++j){
char ch ;
scanf(" %c",&ch);
if(ch == '#'){
mp[i][j] = true;
}
}
}
dfs(1,0);
printf("%d\n",status);
}
return 0;
}