zoukankan      html  css  js  c++  java
  • poj 1321 棋盘问题 (回溯法)

    棋盘问题
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 69951   Accepted: 33143

    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

    题目大意:

    给你一个不规则的棋盘(棋盘见样例),和定量棋子,问有多少种摆放方式,使得棋盘上每行每列都最多只有一枚棋子。

    回溯法的经典题。

    类似八皇后。

    就是逐行搜索,确定每一行棋子放在哪,找到一个解后返回上一步。

    第一次写是参考别人的代码的,用了isok函数,思路比较清晰吧,后来自己优化了一下。

    #include <cstdio>
    
    using namespace std;
    
    int n,k;
    char board[10][10];
    
    int total;
    int c[10];
    
    bool isok(int row)
    {
        if(board[row][c[row]]=='.')
            return false;
        for(int i=0;i<row;i++)
        {
            if(c[i]==-1)
                continue;
            if(c[i]==c[row])
                return false;
        }
        return true;
    }
    
    void queen(int row,int num)
    {
        if(num==k)
        {
            total++;
            return;
        }
        if(row==n)
            return;
        for(int i=0;i<n;i++)
        {
            c[row]=i;
            if(isok(row))
                queen(row+1,num+1);
        }
        c[row]=-1;
        queen(row+1,num);
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&k),n!=-1)
        {
            for(int i=0;i<n;i++)
                scanf("%s",board[i]);
    
            total=0;
            queen(0,0);
            printf("%d
    ",total);
        }
        return 0;
    }
    View Code
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<string>
    #include<iostream>
    #define ll long long
    #define maxn 10000
    
    char board[10][10];
    int n,k;
    int cnt;
    int vis[10];
    
    void queen(int row,int num)
    {
        if(num==0)
        {
            cnt++;
            return;
        }
        if(row+num-1>n)
            return;
        for(int i=1;i<=n;i++)
        {
            if(board[row][i]=='#'&&!vis[i])
            {
                vis[i]=1;
                queen(row+1,num-1);
                vis[i]=0;
            }
        }
        queen(row+1,num);
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&k),n!=-1)
        {
            for(int i=1;i<=n;i++)
                scanf("%s",board[i]+1);
    
            cnt=0;
            memset(vis,0,sizeof(vis));
            queen(1,k);
    
            printf("%d
    ",cnt);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    java线程池及创建多少线程合适
    消息队列消息积压了怎么办?
    Redis线程模型
    redis单线程如何支持高并发
    基于redis实现分布式锁
    PHP面试总结
    【转】Redis入门
    面试常考之二叉树
    计算机网络之面试常考
    操作系统之面试常考
  • 原文地址:https://www.cnblogs.com/acboyty/p/9955176.html
Copyright © 2011-2022 走看看