棋盘问题(带条件的DFS)
题目
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放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
思路
这是一道有条件的DFS(深度搜索)问题,题目所要求的数据量并不是很高,所以直接在满足条件的情况下深搜就好!
1.寻找条件
从题目中我们不难找出本题一共有5个限制条件:
 1.棋盘的大小:n*n
 2.棋子的数量:K个
 3.下棋的位置:必须是在#上
 4.下棋的位置:行上没有棋子
 5.下棋的位置:列上没有棋子
2.应对限制条件
1.棋盘大小
我们在初始化棋盘时,用一个二维数组来代表棋盘,在遍历棋盘时使用两个大小为n的for循环去遍历。
2.棋子的数量
   函数DFS()传入一个变量,表示棋子数量,模拟下棋的棋子变化,每下一次棋,棋子数-1,直到最后棋子数为0时结束这一轮下棋 (做为一种递归退出条件) ,同时也标志着一种可能性的增加
3.下棋的位置
   限制条件在#区域进行操作,将Vis设置为一个一维数组,表示这一列老子都占了,这就很巧妙的规避了一列有相同棋子的情况,而函数DFS()传入一个参数,表示所检查的当前行数,每次递归时从当前位置的下一行进行检查,这就很巧妙的规避了一行有相同棋子的问题。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
#include<string.h>
#include <bits/stdc++.h> 
 
using namespace std;
 
#define LL long long
#define Ios ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0);
#define mem(a,b) memset(a,b,sizeof(a))
 
char Map[9][9]; //开一个二维数组代表N*N的棋盘
int vis[50]; //落一个子后,此子所在的一列全满,表示接下来的步骤不可在此列落
int n,k,ans;
void dfs(int m,int k){
    //棋子没了直接退出本次模拟,并且方案数++
    if(k==0){
        ans++;
        return ;
    }
    //两层循环为解决限制条件1
    for(int i=m;i<n;i++)
        for(int j=0;j<n;j++){
        if(Map[i][j]=='.'||vis[j]==1) continue; //有子不落,或者白不落
        else{
            vis[j]=1; //落一个子后,此子所在的一列全满,表示接下来的步骤不可在此列落
            dfs(i+1,k-1); //直接检查下一行,此行不检查保证此行只落一个子,并且棋子数-1
            vis[j]=0; //要进行下一轮的模拟了,把上一轮落下的棋子拿掉,这里是回溯的思想
        }
    }
}
int main(){
     while(scanf("%d%d",&n,&k) != EOF){
        if(n==-1&&k==-1)
            break;
        for(int i=0;i<n;i++)
            scanf("%s",&Map[i]);
        mem(vis,0);
        ans=0;
        dfs(0,k);
        printf("%d\n",ans);
    }
    return 0;
}
 
                   
                   
                   
                   本文介绍了一个特定的深度优先搜索(DFS)问题——在给定形状的棋盘上摆放棋子,要求任意两个棋子不在同一行或列。通过分析问题特点,采用DFS算法求解所有可能的摆放方案。
本文介绍了一个特定的深度优先搜索(DFS)问题——在给定形状的棋盘上摆放棋子,要求任意两个棋子不在同一行或列。通过分析问题特点,采用DFS算法求解所有可能的摆放方案。
           
       
           
                 
                 
                 
                 
                 
                
               
                 
                 
                 
                 
                
               
                 
                 扫一扫
扫一扫
                     
              
             
                   3061
					3061
					
 被折叠的  条评论
		 为什么被折叠?
被折叠的  条评论
		 为什么被折叠?
		 
		  到【灌水乐园】发言
到【灌水乐园】发言                                
		 
		 
    
   
    
   
             
            


 
            