棋盘问题 dfs分层搜索(n皇后变式)

棋盘问题

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 47960   Accepted: 23210

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

类似n皇后问题,比n皇后少了一种斜向判断的情况,棋盘不再是方形。开始用的是dfs裸搜,每一步从头到尾枚举#放棋情况,放置后赋‘ . ‘。发现最后的结果含重复的情况,考虑到棋子放在相同位置时有全排列的k!种情况,再把结果/k!,果断TLE。。在尝试8*8棋盘时,就已经很难跑出结果了,所以考虑dfs怎样才能从根本避免搜索出现重复情况,我的想法是分层次搜索,因为一行只放一个棋子,所以以每一层为一个深度,向下搜索,这样大大优化了时间效率,8*8的极限情况也能110ms轻松跑出。

#include<stdio.h>

char a[10][10];
int row[10],col[10];
int n,m,c;

void dfs(int x,int s)
{
    int i,j;
    if(s==m){
        c++;
        return;
    }
    for(i=x;i<n;i++){
        for(j=0;j<n;j++){
            if(a[i][j]==‘#‘&&row[i]==0&&col[j]==0){
                a[i][j]=‘.‘;
                row[i]=1;
                col[j]=1;
                dfs(i,s+1);
                a[i][j]=‘#‘;
                row[i]=0;
                col[j]=0;
            }
        }
    }
}
int main()
{
    int i;
    while(scanf("%d%d",&n,&m)&&!(n==-1&&m==-1)){
        for(i=0;i<n;i++){
            getchar();
            scanf("%s",a[i]);
        }
        c=0;
        dfs(0,0);
        printf("%d\n",c);
    }
    return 0;
}
时间: 2024-10-11 22:59:50

棋盘问题 dfs分层搜索(n皇后变式)的相关文章

&lt;DFS搜索&gt; N皇后问题

N皇后问题 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 高斯认为有76种方案.1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果.,由此演变出N皇后问题: 下面给出N皇后的两种求解方式: 第一种方式:DFS直接搜索 代码: <span style="font

用位运算解决皇后问题以及皇后变体问题

问题描述: N皇后问题或者如下皇后变体问题: 在一个6*6的棋盘里放置4个互不攻击的车的方案数为多少?(阿里2016实习生在线笔试题) #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int n,m,goal; int ans,sum; void DFS(int row,

POJ 1321 棋盘问题 --- DFS

POJ 1321 棋盘问题 http://poj.org/problem?id=1321 /*POJ 1321 棋盘问题 --- DFS*/ #include <cstdio> #include <cstring> int n, k, cnt; bool visit[10]; //标记列的访问状态 char mapp[10][10]; /*从第r行开始正确放置p个棋子*/ void dfs(int r, int p){ if (p == 0){ ++cnt; return; } i

DFS深度搜索的一般思想

对于无向图来说DFS深度搜索 递归思想 //深度优先搜索DFS的一般实现 void DFS(MGraph G,int i)//DFS递归思想 { int j; visited[i]=TRUE;//设置Node已经被访问 printf("%c",G.vexs[i]); for(j=0;j<numVertexes;j++)//对此Node跟Node2(j)遍历 如果arc[][]==1则表明当前DFS的Node与Node2(j)连通,且满足Node2未被访问的条件下 则对Node2进

DFS 深度优先搜索例题

约翰的农场被暴风雨给淹没了,损失很大,他的保险公司将支付给他,但是支付金额取决于被淹没的最大面积.这个农场是一个边长分别为n.m的矩形,包含nm个空间,每个空间要么是干的,要么是被淹没的,一共有k个空间被淹没.求最大的淹没面积. 题目分析:首先建立坐标,标记被淹没的空间,然后从左上角搜索被淹没的空间,并取消标记,再以此为中心向四周搜索是否有被淹没的空间,有的话继续计数并取消标记,以此类推,找出所有被淹没的空间,最后排序,找到被淹没最大的面积. #include <stdio.h>#includ

C#报表查询区域变式存储内容条件

双击调用存储的变式条件

汉诺塔问题及其变式

先盗一张图: 正常的汉诺塔问题只要把A柱的所有盘子移动到C柱就好了,可以借助B柱.实现的逻辑如下: void hanoi(int n,char a,char b,char c) { ans++; if(n==1) { cout<<a<<"->"<<c<<endl; return; } hanoi(n-1,a,c,b); cout<<a<<"->"<<c<<en

表维护的变式说明

标准设置指的是默认用哪个变式.里边有自定义的变式和“基本设置”变式.“基本设置”变式是点“管理员”按钮进去设置的,是所有用户都可用的. 当前设置是当前界面上正在使用哪个变式. 原文地址:https://www.cnblogs.com/sap-George/p/11198780.html

POJ 1321 棋盘问题 DFS搜索

简单搜索 练习一下回溯 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <sstream> 5 #include <string> 6 #include <algorithm> 7 #include <list> 8 #include <map> 9 #include <vector> 10 #inc