POJ 1321 棋盘问题(dfs)

来源:互联网 发布:热血尖兵知乎 编辑:程序博客网 时间:2024/06/05 18:16

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
Solution
dfs
由于只要放k个棋子,且有些行不能放棋子。所以可以先预处理一下,看哪些行需要放棋子。处理当前行的时候有两种状态,一是在当前航放棋子,二是不放棋子。放棋子就判断是否有相同列,不放棋子则直接深搜下一行
Code

#include<cstdio>#include<iostream>using namespace std;#define maxn 10char map[maxn];int f[maxn][maxn];int v[maxn];//列标记 int n,k;int ans;//状态计数器  void dfs(int x,int s)//逐行搜索,x为当前搜索行,s为已填充的棋子数 {    if(s==k)    {        ans++;        return ;    }    int j;    if(x>n)//配合下面DFS(x+1,num)使用,避免搜索越界        return ;    for(j=1;j<=n;j++)        if(f[x][j]&&v[j])        {            v[j]=0;//放置棋子的列标记            dfs(x+1,s+1);            v[j]=1;//回溯后,说明摆好棋子的状态已记录,当前的列标记还原         }    dfs(x+1,s);//这里是难点,当k<n时,x在等于n之前就可能已经把全部棋子放好               //又由于当全部棋子都放好后的某个棋盘状态已经在前面循环时记录了             //因此为了处理多余行,令当前位置先不放棋子,搜索在下一行放棋子的情况 }int main(){    while(scanf("%d%d",&n,&k))    {        if(n==-1&&k==-1)//输入结束             break;        for(int i=1;i<=n;i++)        {            scanf("%s",map+1);            for(int j=1;j<=n;j++)                if(map[j]=='.')                    f[i][j]=0;                else                    f[i][j]=1;            v[i]=1;        }        ans=0;        dfs(1,0);//注意初始化的值        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击