poj 1321 棋盘问题 dfs

来源:互联网 发布:剑网南风捏脸米苏数据 编辑:程序博客网 时间:2024/06/06 11:42
C - 北京大学推免生机考D题
Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%lld & %llu
Submit Status Practice POJ 1321

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

思路:一道比较简单的dfs题目,有点类似N皇后问题,我用了两种方法,因为这个问题要求我们放的棋子数k可能少于棋盘的n,

也可能相等,如果相等话好说每一行每一列上都有,直接dfs标记一下就行了,我们需要考虑的就是k<n的时候;

第一种:我是标记的列然后每次对行dfs就不会放在同行同列了

#include<stdio.h>#include<string.h>char a[10][10];int s[10][10];int flag[10];int n,k,count;void dfs(int row,int num){         int i;     if(num==k)  {    count++;    return ; }     if(row>=n)       return ;       for(i=0;i<n;i++)       {   if(s[row][i]==1&&flag[i]==0)            {    flag[i]=1;                 dfs(row+1,num+1);                 flag[i]=0;}   }   dfs(row+1,num);//这个地方可能比较难理解,这是对k<n情况的处理,当放完这一行,回溯的时候,因为k<n,所以我们要跳过这一行去找下一行满足条件的,一直到row》=n结束;}int main(){   while(scanf("%d %d",&n,&k)!=EOF)   {     if(n==-1&&k==-1)           break;           memset(flag,0,sizeof(flag));           memset(s,0,sizeof(s));           count=0;         int i,j;         for(i=0;i<n;i++)         scanf("%s",a[i]);         for(i=0;i<n;i++)          for(j=0;j<n;j++)            {  if(a[i][j]=='#')              s[i][j]=1;              else              s[i][j]=0;}  dfs(0,0);  printf("%d\n",count);                        }    return 0;}
第二种方法:
//我是这样想的,如果k<n,那么第一个棋子最大只能放到第n-k行(从0开始),那么他的下一行最大只能放到n-num+1行,也是标记列,对行dfs,得出结果,还挺快的0ms
#include<stdio.h>#include<string.h>char a[10][10];int s[10][10];int flag[10];int n,k,count;void dfs(int row,int num){         int i,j;     for(j=0;j<n;j++)      { if(s[row][j]==1&&flag[j]==0) {    if(num==1)  {    count++; }     else       {    flag[j]=1;     for(i=row+1;i<n-num+2;i++)             dfs(i,num-1);            flag[j]=0;      }       }       }}int main(){   while(scanf("%d %d",&n,&k)!=EOF)   {     if(n==-1&&k==-1)           break;           memset(flag,0,sizeof(flag));           memset(s,0,sizeof(s));           count=0;         int i,j;         for(i=0;i<n;i++)         scanf("%s",a[i]);         for(i=0;i<n;i++)          for(j=0;j<n;j++)            {  if(a[i][j]=='#')              s[i][j]=1;              else              s[i][j]=0;}              for(i=0;i<=n-k;i++)  dfs(i,k);  printf("%d\n",count);                        }    return 0;}

本人搜索学的比较糙,如果哪里不对,或者大神有更好的见解,欢迎大家留言一起交流!

1 0
原创粉丝点击