zoukankan      html  css  js  c++  java
  • 棋盘问题 POJ 1321

    总时间限制: 1000ms 内存限制: 65536kB
    描述
    在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
    输入
    输入含有多组测试数据。
    每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
    当为-1 -1时表示输入结束。
    随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
    输出
    对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
    样例输入
    2 1
    #.
    .#
    4 4
    ...#
    ..#.
    .#..
    #...
    -1 -1
    
    样例输出
    2
    1

    分析:

    类似于八皇后问题,把每一行当做一个阶段(或者说状态),每一个阶段(状态)有若干种选择(当前行有若干列)。

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 int n,k;
     5 int book[100],ans;
     6 char a[100][100];
     7 void f(int x,int num)//往第x行摆放第num个棋子 
     8 {
     9     if(x>n) return ;
    10     
    11     for(int i=1;i<=n;i++)
    12     {
    13         if(a[x][i]=='#'&&book[i]==0)
    14         {
    15             if(num==k)    { ans++; continue;}
    16             book[i]=1;
    17             f(x+1,num+1);
    18             book[i]=0;
    19         }
    20     }
    21     f(x+1,num);
    22     return ;
    23 }
    24 int main()
    25 {
    26     while(1)
    27     {
    28         cin>>n>>k;
    29         memset(book,0,sizeof(book));
    30         ans=0;
    31         if(n==-1&&k==-1)    return 0;
    32         for(int i=1;i<=n;i++)
    33             for(int j=1;j<=n;j++)
    34                 cin>>a[i][j];
    35         f(1,1);
    36         cout<<ans<<endl;
    37     }
    38     return 0;
    39 }
    何明星的深搜
     1 #include <iostream>
     2 using namespace std;
     3 char chess[9][9]={0};
     4 int n,k;
     5 int num;
     6 int deline[9]={0};
     7 void f(int x,int y)//第x行,已经放了y颗棋子 
     8 {
     9     if(y==k) {num++;return; }
    10     if(x==n) return;
    11     for(int i=0;i<n;i++)
    12         if(chess[x][i]=='#')
    13             if(deline[i])
    14             {
    15                 deline[i]=1;
    16                 f(x+1,y+1);
    17                 deline[i]=0;
    18             }
    19     f(x+1,y);
    20     return;
    21 }
    22 
    23 int main()
    24 {
    25     while(cin>>n>>k){
    26         if(n==-1&&k==-1) break;
    27         num=0;
    28         for(int i=0;i<n;i++) deline [i]=0;
    29         for(int i=0;i<n;i++)
    30             cin>>chess[i];
    31         f(0,0);
    32         cout<< num<<endl;
    33     }
    34     return 0;
    35 }
    韦泽鸿的深搜
     1 #include <stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 using namespace std;
     5 int qq[10][10],k,n,sum,pd[10],way;
     6 void look(int r)//处理第r行 
     7 {
     8     if(way==k) {sum++;return;}
     9     if(r>n) return;
    10     for(int i=1;i<=n;i++)//往第r行放棋子 
    11         if(qq[r][i]==1&&pd[i]==0)
    12         {
    13             
    14             pd[i]=1;way++;
    15             look(r+1);
    16             pd[i]=0;way--;
    17         }
    18     look(r+1);//第r行不放棋子 
    19 }
    20 int main()
    21 {
    22     while(1)
    23     {
    24         way=0;sum=0;
    25         scanf("%d%d",&n,&k);
    26         if(n==-1&&k==-1) break;
    27         memset(pd,0,sizeof(pd));
    28         memset(qq,0,sizeof(qq));
    29         
    30         for(int i=1;i<=n;i++)
    31             for(int j=1;j<=n;j++)
    32             {
    33                 char t;
    34                 cin>>t;
    35                 if(t=='#') qq[i][j]=1;
    36             }
    37         
    38         look(1);
    39         printf("%d
    ",sum);
    40     }
    41     return 0;
    42 }
    刘俊东的深搜

    下面是网络上摘抄来的代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <set>
     7 #include <queue>
     8 #include <stack>
     9 
    10 using namespace std;
    11 char map[10][10];
    12 int vis[10];//第i列是否放置了棋子
    13 int cnt;//已放棋子的数目
    14 int sum;//放置方法的总数
    15 int n,k;
    16 void dfs(int s)
    17 {
    18     int i;
    19     if(cnt==k){//所有的棋子都放置好
    20         sum++;
    21         return ;
    22     }
    23     else{
    24         if(s>=n)//如果越界
    25             return ;//返回
    26         else{
    27             for(i=0;i<n;i++){//讲一个棋子尝试放在0-n-1列的某一行
    28                 if(map[s][i]=='#'&&!vis[i]){
    29                     vis[i]=1;//标记该列已经放了棋子
    30                     cnt++;//棋子数+1
    31                     dfs(s+1);//继续搜索
    32                     cnt--;//经过一轮递归后num始终保持不变,因为没有放棋子
    33                     vis[i]=0;//在此处不放棋子
    34                 }
    35             }
    36             dfs(s+1);//进行剩下的k-1个棋子的遍历
    37         }
    38     }
    39 }
    40 int main()
    41 {
    42     int i;
    43     while(~scanf("%d %d",&n,&k)){
    44             getchar();
    45         if(n==-1&&k==-1) break;
    46         memset(vis,0,sizeof(vis));
    47         for(i=0;i<n;i++)
    48             scanf("%s",map[i]);
    49     cnt=sum=0;
    50         dfs(0);
    51         printf("%d
    ",sum);
    52     }
    53     return 0;
    54 }

    参考: http://blog.csdn.net/u013486414/article/details/43878071

  • 相关阅读:
    安装WebStorm
    Could not obtain transaction-synchronized Session
    Hibernate4 No Session found for current thread原因
    Spring3系列7- 自动扫描组件或Bean
    论坛角色
    firefox浏览器无法显示bootstrap图标问题总结
    express文件上传中间件Multer最新使用说明
    判断圆和矩形是否相交C
    转化为用欧几里得算法判断互质的问题D
    (记录前面算过的后面仍然会用的数减小复杂度)A
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/7471031.html
Copyright © 2011-2022 走看看