第1次实验——NPC问题(回溯算法、聚类分析)

实验要求链接:戳我

(1)八皇后及N皇后问题      八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。      请编程实现八皇后问题,并把92种解的前三种解输出到屏幕(8*8的二维矩阵,Q代表皇后,X代表空)。并把此问题的求解过程延伸到N皇后问题。

/* 在 n 行 n 列的国际象棋棋盘上,最多可布n个皇后。
 *  若两个皇后位于同一行、同一列、同一对角线上, 则称为它们为互相攻击。 
 *  n皇后问题是指找到这 n 个皇后的互不攻击的布局。
 *   n 行 n 列的棋盘上,主次对角线各有2n-1条。
 *    利用行号i和列号j计算 主对角线编号k的方法是k = n+i-j-1; 计算次对角线编号k的方法是k = i+j  
 *    */
package org.geolem.source.queen;
/**
 * @author yanghuazhi
 *
 */

public class Queen { 
	int n;    //皇后问题的大小 
	int col[]; //数组,各列上有无皇后(0,1) 
	int md[];  //数组,各主对角线有无皇后(0,1) 
	int sd[];  //数组,各次对角线有无皇后(0,1) 
	int q[];  //数组,第i行上皇后在第几列(0,n-1) 
	int Q;    //已布皇后数,计数
	int r;    //n皇后问题的解的组数 
	//构造函数 n皇后问题的初始化
	public Queen(int m) {     
		n=m;
		Q=0;
		r=0;  
		col=new int[n];   
		md=new int[2*n-1];  //初始化0  
		sd=new int[2*n-1];  
		q=new int[n]; 
		}
	//函数:打印棋盘
	public void showBoard() {  
		int i,j; 
		for(i=0;i<n;i++) {  
			for(j=0;j<n;j++)   
				if(q[i]==j)
					System.out.print("Q ");  
				else System.out.print("X ");  
			System.out.println(); 
			} 
		r++;
		//解的组数 
		System.out.println("==============="); 
		} 
	//求解n皇后问题 
	/*  此函数试图在n*n的棋盘的第i行上放一个皇后,  若找到可以放的位置,就递归调用自身试图在i+1行  放另一个皇后,若第i行是最后一行,则打印棋盘。 */ 
	public void resolve(int i) {  
		int j;   
		// 在第i行给定后检查棋盘上的每一列 
		for(j=0;j<n;j++) {  
			//如果在第i行的第j列可以布放皇后  
			if(col[j]==0&&md[n+i-j-1]==0&&sd[i+j]==0){  
				Q++;q[i]=j; //布放皇后,第i行皇后在第几列       
				// 标记新布皇后的攻击范围   
				col[j]=md[n+i-j-1]=sd[i+j]=1;       
				// 如果已经布了n个皇后(得到了一组解),   
				// 把棋盘(解)打印出来。 
				if(Q==n) showBoard();    
				// 否则,递归。在第i行第j列布放皇后的前提下,    
				//试探下一行(i+1行)在哪一列布皇后? 
				else if(i<n-1) resolve(i+1);    
				else resolve(0); //因为约定起始行可以任选   
				//移除在第i行的第j列新布的皇后,  
				//并消除所标记的攻击范围,为回溯作准备。  
				Q--; 
				q[i]=0;  
				col[j]=md[n+i-j-1]=sd[i+j]=0;   
				//试探在第i行的第j+1列新布皇后的方案(新解)  
				}    
			} //下一列,j循环 
		//对于给定的行,列扫描完毕后,从这里回溯。
		} 
	//输出解的个数 
	public void HowMany() {  
		System.out.println(n+"皇后问题共有解"+r+"组。");
		}  
	//主方法main() 
	public static void main(String []args) { 
		//定义一个8皇后问题(有92组解) 
		Queen  Q1=new Queen(8);  
		//大于10,你的微机可能要死机!  
		//第一个皇后可以在任意一行布放
		Q1.resolve(0);  
		//参数在0到n-1之间任选  
		Q1.HowMany();
		}
	}  


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值