蓝桥杯 BASIC-27 基础练习 2n皇后问题

问题描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出

0


分析:

首先,考虑,普通的八皇后问题是怎么实现的。

①遍历每一个位置,n*n每一个位置,每次遍历的时候判断,该位置是否能放下旗子。

②使用一个一维数组保存每一列的位置。原因。因为每一行是不可以放置重复旗子的。

使用一维数组。 每一个坐标代表行号。 。。   该坐标里面的值代表这一行,这一列 在哪个位置放下旗子


使用一维数组可以减少遍历次数


2n皇后实现:

每次遍历出一个  只放置 黑色棋子 的棋盘 放法。

复制出一个棋盘。 所有已放置黑色棋子的位置 设置为0  代表已经不可以放置棋子了。

遍历出该棋盘所有 可以放置的白棋子位置的方法

import java.util.*;
public class Main {
    	
		static int n ;
		static int count = 0;//次数和
		
        public static void main(String[] args) {
           Scanner input = new Scanner(System.in);
           n = input.nextInt();
           int[][] begin = new int[n][n];
           int[] pos = new int[n];//方便遍历的一维数组
           
           for(int i=0;i<n;i++){
        	   for(int j=0;j<n;j++){
        		   begin[i][j] = input.nextInt();
        	   }
           }
           setBlack(begin,pos,0);//开始测试所有黑色棋子摆放方式
           
           System.out.println(count);
           
        }
      
        
        public static boolean isSafe(int[] pos,int row){//验证该行放置的旗子是否和其他行冲突
        	
        	for(int i=0;i<row;i++){
        		 if(pos[i]==pos[row]||Math.abs(i-row)==Math.abs(pos[i]-pos[row])){
        			 return false;
        		 }
        	}
        return true;
        }
       
        public static void setBlack(int[][] black,int[] pos,int row){
        	if(row==n){//当所有位置摆放完毕后
        		
        		int[][] white = new int[n][n];
        		int[] pos1 = new int[n];
        		//按照现在已经摆满黑棋子的情况,创造出一个新的棋盘
        		for(int i=0;i<n;i++){
        			for(int j=0;j<n;j++){
        				if(black[i][j]==1&&pos[i]!=j){//该位置没有放置白棋子,并且原本可以放置棋子
        					white[i][j] = 1;
        				}
        			}
        		}
        		
        		setWhite(white,pos1,0);
        		
        	}else{
        		//该行的每一列。//试试他能不能放下棋子
        		for(int i=0;i<n;i++){
        			pos[row] = i;
        			if(black[row][i]==1&&isSafe(pos,row)){//判断该位置放棋子对还是错
        				setBlack(black,pos,row+1);
        			}
        		}
        	}
        }
        
        public static void setWhite(int[][] white,int[] pos,int row){
        	if(row==n){
        		count++;
        	}else{
        		for(int i=0;i<n;i++){
        			pos[row] = i;
        			if(white[row][i]==1&&isSafe(pos,row)){
        				setWhite(white,pos,row+1);
        			}
        		}
        	}
        }     
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SUNbrightness

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值