蓝桥杯 Java n皇后&&受伤的皇后&&2n皇后 详解

1、n皇后问题
在 n*n 的棋盘上放置 n 个皇后,使它们不同行、不同列、不同对角线。问有多少种合法的情况。

输入
4
输出
2

输入
8
输出
92

  • 首先我们把这个问题看成具体的皇后数量去思考,比如简单的4皇后
  • 摆放的方式有下面这些情况,因为要求不同行,所以我们可以看到我们每一行一定会放置一个,这样才能放置够n个皇后

在这里插入图片描述

a[ ] 是为了放置皇后的位置
dfs() 函数就是去完成放置皇后的过程,我们首先从第一行开始

import java.util.Scanner;

public class Nking {
	static int n;              //n个皇后
	static int sum=0;           //多少种方法
	static int a[]=new int[100];
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		n=sc.nextInt();  //n个皇后		
		dfs(0);          
		System.out.print(sum);
	}

}

1、dfs(0); 开始是第一行,后面会第二行,第三行,形参是 r 代表行,所以后面就是dfs(r+1);
2、当我们满足(r==n)的时候,我们已经放完最后一行也就是n-1行了,这个时候我们sum++,满足的方式++;

3、for (int c = 0; c < n; c++) 这里的for循环是为了,列出同行不同列的所有情况
4、 a[r]=c; a数组是为了存储放置皇后的位置,r 是代表行,a[r] 代表列

5、check(r,c)是一个函数:r行c列的这个位置是否能够放置皇后,也就是和前面的皇后不冲突,也就是和前面的皇后不同行不同列不同对角线

import java.util.Scanner;

public class Nking {
	static int n;
	static int sum=0;           //多少种方法
	static int a[]=new int[100];

	static void dfs(int r) { //r行
		if(r==n)   //结束条件
			sum++;
			for (int c = 0; c < n; c++) {	   //枚举r行可以放置的列   
				if(check(r,c)) {  //约束条件:r行c列是否可以放置皇后,r行c列满足不同行同列同对角线
					a[r]=c;     //放置皇后的位置保存起来
					dfs(r+1);
				}
			}	
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		n=sc.nextInt();  //n个皇后		
		dfs(0);
		System.out.print(sum);
	}

}

check(int r, int c)函数判断是否满足条件,那我 r 行 c 列要和前面的皇后进行比较,因为我是一行一行往下面走的,所以我们肯定不同行,a[i]==c 说明同列,
Math.abs(r-i)==Math.abs(c-a[i]) 说明同对角线

Math.abs()是取绝对值的意思

//完整代码如下
import java.util.Scanner;

public class Nking {
	static int n;
	static int sum=0;           //多少种方法
	static int a[]=new int[100];
	static boolean check(int r, int c) {  //r行c列是否可以放置皇后
		for (int i = 0; i < r; i++) {
			//和之前的皇后进行比较(也就是r的前面行)判断是否冲突 (不要同列同对角线)
			if(a[i]==c || Math.abs(r-i)==Math.abs(c-a[i]))     //同一列或者同一个对角线  
				return false;
		}	
		return true;
	}
	static void dfs(int r) { //r行
		if(r==n)   //结束条件
			sum++;
			for (int c = 0; c < n; c++) {	   //枚举r行可以放置的列   
				if(check(r,c)) {  //约束条件:r行c列是否可以放置皇后,r行c列满足不同行同列同对角线
					a[r]=c;     //放置皇后的位置保存起来
					dfs(r+1);
				}
			}	
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		n=sc.nextInt();  //n个皇后		
		dfs(0);
		System.out.print(sum);
	}

}

2、受伤的皇后
题目描述
有一个n×n 的国际象棋棋盘(n 行 n 列的方格图),请在棋盘中摆放 n 个受伤的国际象棋皇后,要求:
任何两个皇后不在同一行。
任何两个皇后不在同一列。
如果两个皇后在同一条 45 度角的斜线上,这两个皇后之间行号的差值至少为 3
请问一共有多少种摆放方案。
输入描述
输入的第一行包含一个整数 n。
其中,1≤n≤10。
输出描述
输出一个整数,表示答案。

输入
4
输出
2

输入
8
输出
1290

1、题目就是多加了一个如果两个皇后在同一条 45 度角的斜线上,这两个皇后之间行号的差值至少为 3 ,和之前的题目相比就是可以同对角线了,只是之间的行号差值要>=3
2、也就是在check函数进行判断的地方进行修改,多加一个 r - i < 3

import java.util.Scanner;
//放置n皇后
public class DFS2 {
	static int a[]=new int[100];  //存储皇后放置的位置
	static int sum=0;
	static int n;
	static boolean check(int r,int c) {
		for (int i = 0; i <r ; i++) {
			if(a[i]==c)
				return false;
			if(Math.abs(r-i)==Math.abs(c-a[i]) && r-i<3)
				return false;
		}             //满足条件,不在同行同列同3步对角线内			
		return true;
	}
	static void dfs(int r) {  //r行
		if(r==n)              //结束状态
			sum++;
		for (int c = 0; c < n; c++) {  //r行 c列
			if(check(r,c)) {              //满足条件,不在同行同列同3步对角线内
				a[r]=c;                //放置皇后
				dfs(r+1);
			}
		}
		
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		n=sc.nextInt();  //n个皇后		
		dfs(0);
		System.out.print(sum);
		
	}

}

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

先放一个皇后,之后再放另一个皇后
放之前要多加一个判断,这个位置是否为1

import java.util.Scanner;
/*
输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
输出
2

输入
8
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
输出
3252
*/
public class NNking {
	static int res;	//结果 
	static int n;		//皇后个数 
	static int a[]=new int[10];	//存储白皇后每行所放列位置,下标为行的位置 ,n不定,定义最大值10 
	static int b[]=new int[10]; 	//存储黑皇后每行所放列位置
	static int map[][] =new int[10][10];// 存储棋盘,当map[i][j]=1,表示当前位置可放 

	static boolean check_a(int r,int c)
	{
		for(int i=0;i<r;i++)	//和已知的每一行皇后判断是否冲突 
			if(c==a[i] || Math.abs(r-i)==Math.abs(c-a[i]))
				return false;
		return true;
	 } 
	 
	static boolean check_b(int r,int c)
	{
		for(int i=0;i<r;i++)	//和已知的每一行皇后判断是否冲突 
			if(c==b[i] || Math.abs(r-i)==Math.abs(c-b[i]))
				return false;
		return true;
	 } 

	static void dfs_b(int r)//黑皇后遍历过程 
	{
	    if(r==n){
			res++;
		}
	    else{
	        for(int c = 0; c < n; c++){  	  
	           if(map[r][c]==1&&check_b(r,c)) {    // map[r][c]==1才可放置  非同行同列同对角
	               	map[r][c]=0;                //放置后置位0
	                b[r] = c;				//记录当前白皇后放置的位置,即第r行放第c列 
	                dfs_b(r+1);
	                map[r][c]=1;           
	 }}}}

	static void dfs(int r)//先是白皇后遍历过程  第r行 
	{
	    if(r==n){
			dfs_b(0);  //遍历黑皇后
		}
	    else{
	        for(int c = 0; c < n; c++){   
	           if(map[r][c]==1&&check_a(r,c)) {   // map[r][c]==1才可放置  非同行同列同对角
			   		map[r][c]=0;   					//放置后置位0
	                a[r] = c;				//记录当前白皇后放置的位置,即第r行放第c列 
	                dfs(r+1);
	                map[r][c]=1;           //尝试另外一条路,要把刚刚走过的改回1
	}}}}



	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		n=sc.nextInt();  //n个皇后	
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
			{
				map[i][j]=sc.nextInt(); //棋盘存储到map数组
			}
		dfs(0);
		System.out.print(res);
	}

}
  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值