poj 1312(详解)棋盘问题

来源:互联网 发布:网络视频传输方案 编辑:程序博客网 时间:2024/05/17 05:06

棋盘问题
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 41236 Accepted: 20128

Description

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。

Input

输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。

Output

对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。

Sample Input

2 1#..#4 4...#..#..#..#...-1 -1

Sample Output

21

思路:经典题,通过这题,圆满的理解了dfs的递归调用,详看代码;

体会:回溯法的经典结合,学长告诉zz这是模拟栈,zz体会到了,并且通过dfs搜索的树,稍微理解了一点;

#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>using namespace std;int n,k,res;char ma[110][110],v[1010];void dfs(int x,int y){if(y==k){res++; return;//结束递归;}  for(int i=x;i<=n;i++)//找出此行所有的结果;代表行{for(int j=1;j<=n;j++)//从1到n遍历第i行的所有字符;代表列{if(ma[i][j]=='#' && !v[j]){v[j]=1;//标记此列的#用过; dfs(i+1,y+1);v[j]=0;//初始用过的v[j]; }}}}int main(){int i,j;while(scanf("%d %d",&n,&k) && (k+n>=0)){memset(ma,0,sizeof(ma));memset(v,0,sizeof(v));//标记列的#是否用过; for(i=1;i<=n;i++){getchar();for(j=1;j<=n;j++){scanf("%c",&ma[i][j]);}}res=0;dfs(1,0);//第一个字符开始搜索,满足条件的#为0; printf("%d\n",res);}return 0;}

1 0