• POJ1321 棋盘问题 —— DFS回溯


    题目链接:http://poj.org/problem?id=1321


    棋盘问题
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 50263   Accepted: 24352

    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
    

    Source



    题解:

    类似于八皇后问题。

    由于题目要求放k个,不像八皇后那样固定了8个,所以在一开始时不知道怎样处理“k个”。即如果实际能放的位置比k要大时该怎么处理

    一开始是想:在能够放的地方,执行两种操作,放和不放。但是却会出现重复,因为对于一行,不放的位置可以是多个,这就有了多种情况,但实际上这多种情况都是一样的,因为对于接下来的行,所呈现的状态是一样的。

    正确的操作是:把操作对象从“一个”改为“一行”。对于每一行,有放和不放两种操作,如果不放,则直接跳过;如果放,则再决定放在哪个位置。




    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 #define ms(a,b) memset((a),(b),sizeof((a)))
    13 using namespace std;
    14 typedef long long LL;
    15 const int INF = 2e9;
    16 const LL LNF = 9e18;
    17 const int MOD = 1e9+7;
    18 const int MAXN = 8+10;
    19 
    20 int n, k, ans;
    21 char m[MAXN][MAXN];
    22 int col[MAXN];
    23 
    24 void dfs(int dep, int t)
    25 {
    26     if(dep==n+1)    //到达末时,如果刚好放了k个,则计数器+1
    27     {
    28         if(t==k)  ans++;
    29         return;
    30     }
    31 
    32     dfs(dep+1, t);  //这一行不放
    33     for(int i = 1; i<=n; i++)   //这一行放
    34     {
    35         if(m[dep][i]=='#' && col[i]==0 && t<k )  //t<k为剪枝
    36         {
    37             col[i] = 1;
    38             dfs(dep+1, t+1);
    39             col[i] = 0;
    40         }
    41     }
    42 
    43 //以下为错误的思想
    44 //    for(int i = 1; i<=n; i++)
    45 //    {
    46 //        if(m[dep][i]=='#' && col[i]==0 )
    47 //        {
    48 //            dfs(dep+1, t);    //会出现重复
    49 //            col[i] = 1;
    50 //            dfs(dep+1, t+1);
    51 //            col[i] = 0;
    52 //        }
    53 //    }
    54 
    55 }
    56 
    57 int main()
    58 {
    59     while(scanf("%d%d",&n,&k))
    60     {
    61         if(n==-1 && k==-1) break;
    62 
    63         ms(col,0);
    64         ans = 0;
    65         for(int i = 1; i<=n; i++)
    66             scanf("%s", m[i]+1);
    67 
    68         dfs(1, 0);
    69         cout<< ans <<endl;
    70     }
    71 }
    View Code



  • 相关阅读:
    CSS媒体查询
    搜索关键词标注红色
    揭秘 | 小白如何0基础0元建站
    细说浏览器输入URL后发生了什么
    js问题总结
    vue elementui如何修改el-table头部样式
    h5开发微信公众号重定向到关注页面没有关注按钮 (微信你个坑)
    下拉展开动画
    html中常用的转义字符总结
    9个设计师常用的高清图库 不敢配图? 这9个免版权图库牢记心中!
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7538600.html
Copyright © 2020-2023  润新知