永夜初晗凝碧天

本博客现已全部转移到新地址,欲获取更多精彩文章,请访问http://acshiryu.github.io/

导航

POJ1321 棋盘问题 解题报告

分类:DFS,迷宫,棋盘
作者:ACShiryu
时间:2011-7-24
棋盘问题
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 11884 Accepted: 5833

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

2
1
简单搜索题,题目意思很明了,其中'#'可以放棋子,'.'不能,并且同一行或同一列不能放两个棋子,
对于数据一游两种放法('*'代表放的棋子)
*.      #.
.#  或  .*
对于数据二只有一种情况
...*
..*.
.*..
*...
这题只需要深搜,每次从上一个放棋子地方的下一行开始寻找可以放棋子的地方,当发现该点时,记录行数,并更新棋盘,将于此点同行同列的都更新为'.',如果找不到,则返回,当把所有棋子都放上去的时候,则找到一个接,计数+1,就这样进行搜索,可以保证AC

参考代码:

 1 #include<iostream>
2 #include<cstdlib>
3 #include<cstdio>
4 #include<cstring>
5 #include<algorithm>
6 #include<cmath>
7 using namespace std;
8 struct prog {
9 char map [10][10]; //棋盘
10 int x; //上一个棋子的行数
11 };
12 int m; //棋盘大小
13 int ans; //解的个数
14 void DFS(prog tmp,int n)
15 {
16 if(n==0)
17 {//如果要求放的所有棋子都已经放好了,则索命找到了答案,则计数+1并返回
18 ans++;
19 return ;
20 }
21 int i , j ;
22 for ( i = tmp.x + 1 ; i <= m -n; i ++ )
23 {//从上个棋子的下一行开始搜,如果剩余可放棋子数明显大于剩余行数,则可以知道此时无解
24 for ( j = 0 ; j < m ; j ++ )
25 {//从该行的第一个棋盘开始搜到最后一个
26 if ( tmp.map[i][j]=='#')
27 {//如果找到了一点可以放棋子
28 prog tmp2;
29 tmp2=tmp;
30 tmp2.x=i;//记下改点的行数
31 int k;
32 for (k = i+1 ; k < m ; k ++)
33 {//更新棋盘,因为,不会再向该行和该行之前的棋盘搜索,故只用更新该行下同列的棋盘
34 tmp2.map[k][j]='.';
35 }
36 DFS(tmp2,n-1);//放好一个棋子,继续搜
37
38 }
39 }
40 }
41 }
42 int main()
43 {
44
45 int n ; //要求放棋子的多少
46 while ( cin >> m >> n , m != -1 || n != -1 )
47 {
48 ans=0;//初始化为0
49 prog map;
50 map.x=-1;//此时还未放棋子,初始化为-1
51 int i;
52 for ( i = 0 ; i < m ; i ++ )
53 {
54 cin >> map . map [ i ];
55 }
56 DFS(map,n);
57 cout<<ans<<endl;
58 }
59 return 0;
60 }

  

posted on 2011-07-24 11:34  ACShiryu  阅读(3422)  评论(0编辑  收藏  举报