蓝桥杯 2n皇后问题(java)

蓝桥杯 2n皇后问题(java)

问题描述
  给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。

解法描述
这题是一道经典的dfs题,但是与八皇后有所不同,因为要放两种皇后,同时给出的棋盘还有不能放的限制,我们要考虑这两种情况。我在输入棋盘时使用了一个列表来储存棋盘中0的位置,之后在判断该位置是否能放皇后时我们会用到这个列表。

		for(int i = 0; i < n; i++) {
			for(int j =0; j < n;j++) {
				if(input.nextInt() == 0) {
					list.add(i+1);
					list.add(j+1);
				}
			}
		}

我还定义了两个一维数组,分别储存两种棋子的位置,数组下标为行数,内容为列数。使用一维数组会比二维数组简单。初始化讲完,接着就是重点dfs函数,我的方法是先放置好一种颜色的皇后,然后再放置另一种颜色的,所以递归的总层数就是2n,也就是结束条件是当row>2n是结束搜索并使总摆法+1。然后就是当row<=n时进行第一个皇后的摆放,搜索完成后摆放第二种皇后。这里要注意两种皇后判断能否摆放的条件不同,第一种皇后只需要先判断该位置是否可放,因为棋盘中存在0位置不能摆放的问题,这时我们就可以使用上面的list列表来进行判断,然后再进行不在同一行、同一列或同一条对角线上的判断。而第二种皇后要加一个对第一种皇后位置的判断,也就是说第一种皇后放过的位置我们就不能再放了。

public static void dfs(int row) {
		if(row > 2 * n) {
			
			count++;
			return;
		}
		
		if(row <= n) {
			for(int i = 1; i <= n; i++) {
				col1[row] = i;
				if(judge1(row, i)) {
					dfs(row+1);
				}
			}
		}
		else {
			for(int i = 1; i <= n; i++) {
				int temp = row % n;
				if(row % n == 0)temp = n;
				col2[temp] = i;
				if(judge2(temp, i)) {
					dfs(row+1);
				}
			}
		}
	
	}
	
	
	public static boolean judge1(int r, int c) {
		for(int i = 0; i < list.size(); i +=2) {
			if(list.get(i) == r && list.get(i+1) == c) {
				return false;
			}
		}
		
		for(int i = 1; i < r; i++) {
			if(col1[i] == c || (Math.abs(i - r) == Math.abs(col1[i] - c))) return false;
		}
		
		return true;
	}
	
	public static boolean judge2(int r, int c) {
		for(int i = 0; i < list.size(); i +=2) {
			if(list.get(i) == r && list.get(i+1) == c) {
				return false;
			}
		}
		
		for(int i = 1; i < col1.length; i++) {
			if(i == r && col1[i] == c)return false;
		}
		
		for(int i = 1; i < r; i++) {
			if(col2[i] == c || (Math.abs(i - r) == Math.abs(col2[i] - c))) return false;
		}
		
		return true;
	}

完整代码

package Exercise;

import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;

public class towQueens {
	static int n;
	static int[] col1;
	static int[] col2;
	static ArrayList<Integer> list;
	static int count = 0;
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		n = input.nextInt();
		
		col1 = new int[n+1];
		col2 = new int[n+1];
		
		list = new ArrayList<Integer>();
		for(int i = 0; i < n; i++) {
			for(int j =0; j < n;j++) {
				if(input.nextInt() == 0) {
					list.add(i+1);
					list.add(j+1);
				}
			}
		}
	
		dfs(1);
		
		System.out.println(count);
	}

	
	public static void dfs(int row) {
		if(row > 2 * n) {
			
			count++;
			return;
		}
		
		if(row <= n) {
			for(int i = 1; i <= n; i++) {
				col1[row] = i;
				if(judge1(row, i)) {
					dfs(row+1);
				}
			}
		}
		else {
			for(int i = 1; i <= n; i++) {
				int temp = row % n;
				if(row % n == 0)temp = n;
				col2[temp] = i;
				if(judge2(temp, i)) {
					dfs(row+1);
				}
			}
		}
	
	}
	
	
	public static boolean judge1(int r, int c) {
		for(int i = 0; i < list.size(); i +=2) {
			if(list.get(i) == r && list.get(i+1) == c) {
				return false;
			}
		}
		
		for(int i = 1; i < r; i++) {
			if(col1[i] == c || (Math.abs(i - r) == Math.abs(col1[i] - c))) return false;
		}
		
		return true;
	}
	
	public static boolean judge2(int r, int c) {
		for(int i = 0; i < list.size(); i +=2) {
			if(list.get(i) == r && list.get(i+1) == c) {
				return false;
			}
		}
		
		for(int i = 1; i < col1.length; i++) {
			if(i == r && col1[i] == c)return false;
		}
		
		for(int i = 1; i < r; i++) {
			if(col2[i] == c || (Math.abs(i - r) == Math.abs(col2[i] - c))) return false;
		}
		
		return true;
	}

}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据给定的问题描述和代码,这是一个关于蓝桥杯C++题目中的n皇后问题。题目要求在一个n*n的棋盘上放置n个黑皇后和n个白皇后,使得任意两个黑皇后和任意两个白皇后都不在同一行、同一列或同一条对角线上。代码使用递归和回溯的方法来解决这个问题。 代码中的pd1函数用于判断黑皇后的位置是否合法,pd2函数用于判断白皇后的位置是否合法。fang1函数用于放置黑皇后,fang2函数用于放置白皇后。最后,通过调用fang1函数来计算总共有多少种放法。 需要注意的是,代码中使用的p1和p2数组分别表示黑皇后和白皇后的位置,qi数组表示棋盘上每个位置是否可以放皇后。 因此,根据给定的代码,可以计算出总共有多少种放法。 #### 引用[.reference_title] - *1* [蓝桥杯 基础练习 2n皇后问题C/C++(可作DFS练习)](https://blog.csdn.net/qq_43838669/article/details/129306490)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [蓝桥杯2n皇后问题](https://blog.csdn.net/qq_59611494/article/details/128682794)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值