蓝桥杯—2n皇后问题(回溯法)

题目:在这里插入图片描述
在这里插入图片描述
思路:在这里插入图片描述
代码段中的Check();方法没有对同一行之前的位置进行判断,是因为同一行是从左到右依次放置的,若前面放了则直接是下一行的判断,不会是相邻右侧的位置进行放置,则不需要进行判断,同理右侧,下方都不用,因为还没有进行皇后的放置,本题是回溯法经典的应用,递归的思想

import java.util.Scanner;

public class Main {
	static int n,cnt=0;
	static int map[][];
	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		n=in.nextInt();
		map=new int[n][n];
		for(int i=0;i<n;i++)//棋盘具体值的录入(0或1)
			for(int j=0;j<n;j++)
				map[i][j]=in.nextInt();
		put(0,2);//从第一行开始进行白皇后的放置,2表示白皇后,3表示黑皇后
		System.out.println(cnt);
	}
	//放置皇后
	public static void put(int t,int s) {
		//进行当前类型皇后放置是否到达棋盘最后一行
		if(t==n) {
			if(s==2) put(0,3);//若白皇后放置成功,则进行黑皇后放置
			else cnt++;//放置方法找到一种,计量数+1
			return;//当前整体放置过程结束,进行回溯
		}
		//对每一行的值逐个进行操作
		for(int i=0;i<n;i++) {
			if(map[t][i]!=1) continue;//判断当前位置是否为1
			if(check(t,i,s)) {//判断是否满足题目要求,满足则赋值
				map[t][i]=s;
			}else
				continue;//不满足,同一行,下个位置
			put(t+1,s);//下一行皇后的位置
			map[t][i]=1;//回溯的关键
		}
		return;//相应的回溯
	}
	//判断函数
	public static boolean check(int t,int i,int s) {
		for(int q=t-1;q>=0;q--) {//当前位置上方是否进行了相同皇后的放置,这行一下还没放
			if(map[q][i]==s) return false;
		}
		for(int q=t-1,w=i-1;q>=0&&w>=0;q--,w--) {//检查左对角线,这行一下的还没放,不检查
			if(map[q][w]==s) return false;
		}
		for(int q=t-1,w=i+1;q>=0&&w<=n-1;q--,w++) {//检查右对角线,这行一下还没放,不检查
			if(map[q][w]==s) return false;
		}
		return true;
	}
}

法二:

import java.util.Scanner;
public class Main
{
	static int sum=0;//统计符合的数目
	public static void main(String[] args) 
	{
		Scanner db=new Scanner (System.in);
		int n=db.nextInt();
		int arr[]=new int [n]; //皇后放置位置
		int wee[][]=new int [n][n];// 接受输入时的0 1
		for(int i=0; i<n; i++)
			for(int j=0; j<n; j++)
				wee[i][j]=db.nextInt();
		queen(0, 0, arr, wee);//递归调用
		System.out.println(sum);
	}
	public static int queen(int su, int k, int arr[], int[][] wee)
	//su==0表示落子的是白皇后	为1 表示落子的是黑皇后   k表示第k个皇后
	{
		if(k==arr.length)//如果所有皇后都放置
		{
			if(su==0)//判断放置的是否是白皇后
			{
				arr=new int[arr.length];	//如果白皇后都被放置,初始化黑皇后的位置
				queen(su+1, 0, arr, wee);
			}
			if(su==1)//判断放置的是否是白皇后
				sum++;	//统计2n皇后的放置种数
			return sum;
		}
		for(int i=0; i<arr.length; i++)//判断第k个皇后位置(列数)行数为k
		{
			if(wee[k][i]==0)	//如果当前位置坐标值为零,则不能放置皇后
				continue;
			int j;
			for(j=0; j<k; j++)//前k-1个皇后位置(列数)行数 为j
				if(arr[j]==i||Math.abs(arr[j]-i)==(k-j))//判断皇后之间是否存在同一列,统一对角线冲突
					break;
			if(j==k)//条件成立时表示第k个与之前的没有冲突
			{
				arr[k]=i;	//第k个皇后位置
				wee[k][i]=0; //将此位置即为0 表示不能再这放置皇后
				queen(su, k+1, arr, wee);	//递归调用下一层
				wee[k][i]=1;
			}
		}
		return sum;
	}
}

发布了35 篇原创文章 · 获赞 0 · 访问量 680

猜你喜欢

转载自blog.csdn.net/fendouzhilu666/article/details/104729575