POJ 1321-棋盘问题【DFS+递归】

题目链接

题目大意:

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
#include <cstdio>
#include <cstring>
char map[15][15];
int vis[15];
int n, m;
int ans, cas;

void dfs(int row, int num)
{
    if (num == m)ans++;
    else if (n - row < m - num)return;           //如果剩下的函数比需要放的棋子数还要少,那么这种方案肯定行不通,舍弃
    else if (row == n)return;
    else
    {
        for (int i = row + 1; i <=n; i++)             //其实本质还是按照行来进行判断,对于每一行都有两种选择,放还是不放,且每行都只能放一个棋子,所以每次的dfs都是从下一行开始放起
        {                                           
            for(int j=1;j<=n;j++)                     //但由于它并不是每一列都能够放棋子,所以还要对列用一个循环来判断
            {
                if (map[i][j] == '#' && !vis[j])      //由于棋盘每一列只能放一个棋子,所以用一个vis数组来判断当前列是否被放过  
                {
                    vis[j] = 1;
                    dfs(i, num + 1);                 //这一行的这一列放棋子
                    vis[j] = 0;                      //这一行的这一列不放棋子
                }
            }
        }
    }
}

int main()
{
    while (scanf("%d%d", &n, &m) != EOF,n!=-1||m!=-1)
    {
        for (int i = 1; i <=n; i++)
        {
            scanf("%s", map[i]+1);
        }
        memset(vis, 0, sizeof(vis));
        ans = 0;
        dfs(0,0);
        printf("%d
", ans);
    }
    return 0;
}


2018-03-31



作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/00isok/p/8681286.html