POJ 1321 棋盘问题

来源:互联网 发布:安捷伦数据采集仪 编辑:程序博客网 时间:2024/05/24 07:09

题目链接 POJ 1321

棋盘问题
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 28066 Accepted: 13874

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

分析:

深搜,逐行放置棋子,每行放一个,这样就不用判断此行是否有多个棋子了,

用 vis 数组标记每列放置棋子的情况,你猜他是几维数组?一维!是的,vis[ i ] = 1 表示第 i 列放了棋子,

= 0 表示没有放。

对第 x 列,可以放棋子,当然也可以不放,没人强迫你。最后只要放置 k 个就 OK 了。对于清除标记的

问题我也不知道如何表达,就是不让他影响下一次再搜到此处......聪明的你自己好好想想吧。


代码:

#include <cstdio>#include <cstring>#include <iostream>using namespace std;char Cm[10][10];int vis[10], cnt;int n, k;void dfs(int x, int s)      //对第 x 行决策,此时已经放了 s 个{    if(s == k)          //已经放了 k 个    {        cnt++;          //方案数加一        return;         //不再放了,返回    }    if(x >= n) return;  //越界了,返回    for(int i = 0; i < n; i++)          //尝试在第 x 行的第 i 列放棋子    {        if(!vis[i] && Cm[x][i] == '#')  //第 i 列可以放        {            vis[i] = 1;             //标记第 i 列放了棋子            dfs(x + 1, s + 1);      //继续决策下一行            vis[i] = 0;             //清除标记        }    }    dfs(x + 1, s);      //第 x 行不放棋子,直接决策下一行}int main(){    while(~scanf("%d%d", &n, &k))    {        if(n == -1 && k == -1) break;        for(int i = 0; i < n; i++)        {            scanf("%s", Cm[i]);        }        cnt = 0;        memset(vis, 0, sizeof(vis));        dfs(0, 0);              //注意从第 0 行开始        printf("%d\n", cnt);    }    return 0;}



0 0
原创粉丝点击