zoukankan      html  css  js  c++  java
  • POJ 1321 棋盘问题【DFS/回溯/放与不放/类似n皇后】

    棋盘问题
    Time Limit: 1000MS Memory Limit: 10000K
    Total Submissions: 62164 Accepted: 29754
    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

    蔡错@pku
    【分析】:因为棋子的数量k比棋盘数目n少,那么可能有些棋盘区不用放置棋子。这是重点,易错点。
    然后这道题和n皇后有点像,要求同一行、同一列不能放棋子,那么我们一行到下一行逐行搜索,是自然遍历下来的,不用管;就用一个数组标记列放没放棋子,没放过并且是棋盘区就标记可以放,然后回溯(还原现场)进行下一次尝试。
    这里有两种情况,由于只要放k个棋子,且有些行不能放棋子。处理当前行的时候有两种状态,一是在当前行放棋子,二是不放棋子。放棋子就判断是否有相同列,不放棋子则直接深搜下一行。
    而dfs的办法也有几种,常见的有
    1.参数只有一个i表示当前搜索行;
    2.参数有i表示当前搜索行和cnt表示已填充的棋子数 ;
    3.参数有i表示当前搜索行和cnt表示已填充的棋子数 ,双重循环遍历,不用考虑放不放
    【代码】:

    #include<cstdio>
    #include<string>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<set>
    #include<queue>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<cctype>
    #include<stack>
    #include<sstream>
    #include<list>
    #include<assert.h>
    #include<bitset>
    #include<numeric>
    #define debug() puts("++++")
    #define gcd(a,b) __gcd(a,b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define fi first
    #define se second
    #define pb push_back
    #define sqr(x) ((x)*(x))
    #define ms(a,b) memset(a,b,sizeof(a))
    #define sz size()
    #define be begin()
    #define pu push_up
    #define pd push_down
    #define cl clear()
    #define lowbit(x) -x&x
    #define all 1,n,1
    #define rep(i,n,x) for(int i=(x); i<(n); i++)
    #define in freopen("in.in","r",stdin)
    #define out freopen("out.out","w",stdout)
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int,int> P;
    const int INF = 0x3f3f3f3f;
    const LL LNF = 1e18;
    const int maxn = 1e6;
    const int maxm = 10;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int dx[] = {-1,1,0,0,1,1,-1,-1};
    const int dy[] = {0,0,1,-1,1,-1,1,-1};
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int n,k;
    char a[maxm][maxm],v[maxm];
    int cnt,tot;
    
    void dfs(int i)
    {
        if(cnt==k) //当计数器达到k(摆放棋子的数目),不管结果如何都结束了
        {
            tot++;
            return ;
        }
        if(i>=n) return ;
        for(int j=0;j<n;j++)
        {
            if(!v[j] && a[i][j]=='#')
            {
                v[j]=1;
                cnt++;
                dfs(i+1);
                v[j]=0;
                cnt--;
            }
        }
        dfs(i+1); //i行不放棋子
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&k))
        {
            tot=cnt=0;
            ms(a,0);
            if(n==-1&&k==-1) break;
            getchar(); //
    
            for(int i=0;i<n;i++)
                gets(a[i]);
    
            dfs(0);
            cout<<tot<<endl;
        }
    }
    /*
    2 1
    #.
    .#
    4 4
    ...#
    ..#.
    .#..
    #...
    */
    
  • 相关阅读:
    farpoint [转]
    用于主题检测的临时日志(07ebc2e2418343fea17b52c9318e7705 3bfe001a32de4114a6b44005b770f6d7)
    将ColumnFooter显示出来,并对相关属性做适当设置。 SetAggregationType接口可以帮助你方便的完成求和需求。
    单元测试
    c#扩展方法
    String.Format格式说明
    vs 2005断点调试[转]
    EventLog 类【转】
    From Single PDF template Make a series PDF
    PDF template and print
  • 原文地址:https://www.cnblogs.com/Roni-i/p/9191733.html
Copyright © 2011-2022 走看看