今天,上午看了个电影<证人>.-----世界真奇妙,平常的一次撞车,把几个人拉到了一块!.,看的时候,室友说'谢霆锋和<越狱>中m一样流鼻血..呵呵..感觉谢与米勒差远啦,总给人种感觉很轻浮,好像小孩耍帅一样.晕--....然后和同学一块买了套内衣,洗洗澡,下午上课啦,老师划重点,下个星期就考试啦...哦,还有一买东西就被同学'骂'...笨,嘴笨,不会搞价,太幼稚总觉得价钱不会差太远,其实老板太黑啦-----
晚上随便看了些网页,,又把前几天<人工智能>的一个试验题目拿出来,完善了些...(*^__^*) 嘻嘻……,以前没写过技术博客,很差劲,,,,绞尽脑汁忙乎半天,想出的答案,网上一搜,一大堆,答案,还比自己的要好,,并且有些都已经是7,8年前的啦,,,服啦..
不过.....哎,,啥也不说啦..,尽量写下去吧-----孤芳自赏也好,再者,总还有后来者呵1
把皇后问题:
设在初始状态下在国际象棋上没有任何棋子。然后顺序在第
1
行,第
2
行,…,第
n
行上布放棋子。在每一行中有
n
个可选择位置,但在任一时刻,棋盘的合法布局都必须满足
3
个限制条件:即任何两个棋子不得放在棋盘上的同一行、或者同一列、或者同一斜线上。试编写一个算法(递归或者非递归均可),求解并输出此问题的所有合法布局。
首先用非递归实现吧:
1..把棋盘看成一个二维坐标,创建一个Queen类.表示皇后,而每个皇后有一个Point型变量,唯一确定皇后在二维坐标中的位置..且有一个isControl方法,判断是否冲突!
2..解决该问题,用NQueen类,四个变量,含义参考愿程序,主要方法findAndShowAllResults()查找并显示所有解,printResult()getQueen(int index)
3..主要思路:先把第一个皇后放在(0,0)坐标,...
然后getQueen(index)找到一个queenTemp与之前皇后(0-index位置的皇后)都不冲突的位置..
-----------if(不为空)表示找到了,则赋值queenStack[index]queenTemp,同时index+1继续找下一个,止到index+1等于总皇后数;
------------else 为空,表示queeTemp不存在,即表示第index+1个皇后无处安放,则尝试:::把第index个皇后位置后移到下一个合法的位置,重新查找getQueen(index),
:::若后移不可行,则移动第index-1个皇后,一次类推...
4..getQueen(index)//for循环顺次判断坐标(index,y)[y from 0 to queenCount-1]处与index以前的皇后是否冲突...冲突则break跳出for循环尝试(index,y+1)位置....不冲突则完成....若当y=queenCount-1时仍冲突则返回null
代码如下::
import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @author Sunpander
* @version 2008-12-10
*/
public class NQueen {
Queen queenStack[] = new Queen[8]; //存放皇后的数组
int queenCounts = 0; //皇后总数
int queenIndex = 0; //正测试的皇后位置
int resultCount = 0; //解的个数.
public NQueen(){
queenCounts = 8;
queenStack = new Queen[queenCounts];
}
public NQueen( int num)
{
this.queenCounts = num;
queenStack = new Queen[queenCounts];
}
/**
* 在控制台显示结果
*/
public void printResult()
{
if(queenIndex < =0 || resultCount==0)
System.out.println( "无解");
else
{
System.out.println( "第"+resultCount+ "种解法begin:");
for( int k =0;k {
System.out.println( "第 "+(k+1)+ " 个皇后位置:"+queenStack[k]);
}
System.out.println( "end.");
}
}
/**查找并显示所有解,
*
*/
public void findAndShowAllResults()
{
int resultCount =0;
int start = 0;
while(start<=queenCounts-1)
{
queenIndex = 0;
Point point = new Point(0,start); //第一个皇后的位置设置为(k,0);
queenStack[queenIndex] = new Queen(point);
queenIndex ++;
while(queenIndex >=0 && queenIndex <=queenCounts-1)
{
Queen queenTemp;
queenTemp = getQueen(queenIndex);
//queenTemp为null表示上一个queen(即queenIndex--处)的位置导致剩余的queen无法放置
//尝试把queenStack[(--queenIndex)]的y+1;
if( null==queenTemp)
{
boolean flag = true;
while(flag)
{
queenIndex --;
if(queenIndex < 0)
break;
if(queenStack[queenIndex].pos.y == queenCounts-1)
{} //queenStack[(--queenIndex)]的y已经无法在加了,则继续向前看
else
{
queenStack[queenIndex].pos.y++;
queenIndex++;
flag = false;
Point pot = queenStack[queenIndex-1].pos;
for( int index=0;index {
if(queenStack[index].isControl(pot))
{
flag = true;
break;
}
}
}
}
}
else
{
queenStack[queenIndex++]=queenTemp;
}
}
if(queenIndex>0)
{
System.out.println( "第"+(++resultCount)+ "种解法:");
this.printResult();
start = queenStack[0].pos.y+1;
}
else
start++;
}
/**
* 此处08-12-11-16:44-sunpander作修改;:
* 没考虑无解的情况,添加if部分;
*/
if(queenIndex < 0 && (resultCount<=0))
{
System.out.println( "无解");
}
}
/**
*
* @param index
* @return Queen(new Point(index,y))或者null(null表示此路不通)
*/
public Queen getQueen( int index)
{
int x=0,y=0;
boolean isNotOver = true;
while(isNotOver)
{
isNotOver = false;
for( int k=0;k {
//判断坐标(index,y)处是否冲突.冲突则break跳出for循环尝试(index,y+1)位置
if(queenStack[k].isControl( new Point(index,y)))
{
isNotOver = true;
break;
}
}
if(y<=queenCounts-1 && isNotOver)
{
y++;
}
if(y>=queenCounts)
{
return null;
}
}
//不冲突则,返回(index,y)处皇后
return new Queen( new Point(index,y));
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//若只要求输出一个结果..则可直接把第一个皇后固定在(0,0)一次循环就好!;
while( true)
{
int num = 8;
BufferedReader br = new BufferedReader( new InputStreamReader(System.in));
System.out.println( "输入皇后数");
boolean isWrongInput = true;
/**
* 此处08-12-11-16:44-sunpander作修改;:
* 以前没考虑当输入不合法的情况;
* if(str!=null && str!="\r\n")
* num = Integer.parseInt(str);
* else
* System.out.println("输入数字");
*/
while(isWrongInput)
{
try {
String str = br.readLine();
num = Integer.parseInt(str);
} catch (NumberFormatException e) {
System.out.println( "请输入数字(");
isWrongInput = true;
continue;
}
isWrongInput = false;
}
NQueen nq = new NQueen(num);
nq.findResult();
nq.printResult();
//nq.findAndShowAllResults();
}
}
}
/*
*每个皇后为一个类.类有一个变量Point,x表示行,y表示列.pos指定皇后位置.
* 一个isControl方法判断是给定点与皇后位置是否冲突,
*/
class Queen {
Point pos;
public Queen() {
pos = new Point();
}
public Queen(Point pos) {
this.pos = pos;
}
/**
* 判断是给定点与皇后位置是否冲突,需满足即不在同一直线,也不在同一竖线,且不在同一斜线上则不冲突
* 也即看参数Point的x,y与本类对象的point变量的x1,y1满足(x!=x1,y!=y1,x-x1!=y-y1,x+y!=x1+y1
* 都满足则不冲突返回false(即指定的点可以再放皇后!
* @param point
* @return isControl
*/
public boolean isControl(Point point) {
boolean isControl = true;
if (point.x != pos.x
&& point.y != pos.y
&& Math.abs(point.x - pos.x) != Math.abs(point.y - pos.y)
&& Math.abs(point.x + point.y) != Math.abs(pos.x + pos.y))
{
isControl = false;
}
return isControl;
}
public String toString(){
return ( "第"+(pos.x+1)+ "行"+ "第"+(pos.y+1)+ "列");
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @author Sunpander
* @version 2008-12-10
*/
public class NQueen {
Queen queenStack[] = new Queen[8]; //存放皇后的数组
int queenCounts = 0; //皇后总数
int queenIndex = 0; //正测试的皇后位置
int resultCount = 0; //解的个数.
public NQueen(){
queenCounts = 8;
queenStack = new Queen[queenCounts];
}
public NQueen( int num)
{
this.queenCounts = num;
queenStack = new Queen[queenCounts];
}
/**
* 在控制台显示结果
*/
public void printResult()
{
if(queenIndex < =0 || resultCount==0)
System.out.println( "无解");
else
{
System.out.println( "第"+resultCount+ "种解法begin:");
for( int k =0;k
System.out.println( "第 "+(k+1)+ " 个皇后位置:"+queenStack[k]);
}
System.out.println( "end.");
}
}
/**查找并显示所有解,
*
*/
public void findAndShowAllResults()
{
int resultCount =0;
int start = 0;
while(start<=queenCounts-1)
{
queenIndex = 0;
Point point = new Point(0,start); //第一个皇后的位置设置为(k,0);
queenStack[queenIndex] = new Queen(point);
queenIndex ++;
while(queenIndex >=0 && queenIndex <=queenCounts-1)
{
Queen queenTemp;
queenTemp = getQueen(queenIndex);
//queenTemp为null表示上一个queen(即queenIndex--处)的位置导致剩余的queen无法放置
//尝试把queenStack[(--queenIndex)]的y+1;
if( null==queenTemp)
{
boolean flag = true;
while(flag)
{
queenIndex --;
if(queenIndex < 0)
break;
if(queenStack[queenIndex].pos.y == queenCounts-1)
{} //queenStack[(--queenIndex)]的y已经无法在加了,则继续向前看
else
{
queenStack[queenIndex].pos.y++;
queenIndex++;
flag = false;
Point pot = queenStack[queenIndex-1].pos;
for( int index=0;index
if(queenStack[index].isControl(pot))
{
flag = true;
break;
}
}
}
}
}
else
{
queenStack[queenIndex++]=queenTemp;
}
}
if(queenIndex>0)
{
System.out.println( "第"+(++resultCount)+ "种解法:");
this.printResult();
start = queenStack[0].pos.y+1;
}
else
start++;
}
/**
* 此处08-12-11-16:44-sunpander作修改;:
* 没考虑无解的情况,添加if部分;
*/
if(queenIndex < 0 && (resultCount<=0))
{
System.out.println( "无解");
}
}
/**
*
* @param index
* @return Queen(new Point(index,y))或者null(null表示此路不通)
*/
public Queen getQueen( int index)
{
int x=0,y=0;
boolean isNotOver = true;
while(isNotOver)
{
isNotOver = false;
for( int k=0;k
//判断坐标(index,y)处是否冲突.冲突则break跳出for循环尝试(index,y+1)位置
if(queenStack[k].isControl( new Point(index,y)))
{
isNotOver = true;
break;
}
}
if(y<=queenCounts-1 && isNotOver)
{
y++;
}
if(y>=queenCounts)
{
return null;
}
}
//不冲突则,返回(index,y)处皇后
return new Queen( new Point(index,y));
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//若只要求输出一个结果..则可直接把第一个皇后固定在(0,0)一次循环就好!;
while( true)
{
int num = 8;
BufferedReader br = new BufferedReader( new InputStreamReader(System.in));
System.out.println( "输入皇后数");
boolean isWrongInput = true;
/**
* 此处08-12-11-16:44-sunpander作修改;:
* 以前没考虑当输入不合法的情况;
* if(str!=null && str!="\r\n")
* num = Integer.parseInt(str);
* else
* System.out.println("输入数字");
*/
while(isWrongInput)
{
try {
String str = br.readLine();
num = Integer.parseInt(str);
} catch (NumberFormatException e) {
System.out.println( "请输入数字(");
isWrongInput = true;
continue;
}
isWrongInput = false;
}
NQueen nq = new NQueen(num);
nq.findResult();
nq.printResult();
//nq.findAndShowAllResults();
}
}
}
/*
*每个皇后为一个类.类有一个变量Point,x表示行,y表示列.pos指定皇后位置.
* 一个isControl方法判断是给定点与皇后位置是否冲突,
*/
class Queen {
Point pos;
public Queen() {
pos = new Point();
}
public Queen(Point pos) {
this.pos = pos;
}
/**
* 判断是给定点与皇后位置是否冲突,需满足即不在同一直线,也不在同一竖线,且不在同一斜线上则不冲突
* 也即看参数Point的x,y与本类对象的point变量的x1,y1满足(x!=x1,y!=y1,x-x1!=y-y1,x+y!=x1+y1
* 都满足则不冲突返回false(即指定的点可以再放皇后!
* @param point
* @return isControl
*/
public boolean isControl(Point point) {
boolean isControl = true;
if (point.x != pos.x
&& point.y != pos.y
&& Math.abs(point.x - pos.x) != Math.abs(point.y - pos.y)
&& Math.abs(point.x + point.y) != Math.abs(pos.x + pos.y))
{
isControl = false;
}
return isControl;
}
public String toString(){
return ( "第"+(pos.x+1)+ "行"+ "第"+(pos.y+1)+ "列");
}
}
该程序遇到的问题(已解决的):
1,用输入数字时,要考虑转换不合法,或为负等
2.main()方法添加while(isDebug){}用于多次输入判断
3.重写toString()可以直接返回该类表示的意义!
4.开始想简单地用for循环从(0,0)到(0,queenCount-1)执行queenCount-1次,发现,结果可能出现重复.后改正(见程序)
用递归实现
(递归,呵呵,若明白含义,非常简单)
1..首先引用高人的想法,直接用int[]...数组的下标+1表示行数,而该下标的值则表示列数.....
2..主要函数 queen(int nowIndex)
-----------if(nowIndex == queenCount)表示nowIndex之前的皇后已经放好,则直接输出结果
-----------else
for循环试探index(index从1到queenCount)处的queen能否放在地index处,,能即isControl(nowIndex)==false不冲突,则递归queen(index+1)
3...isControl(index)见程序注释
源代码如下:
public class NqueenDigui
{
int queenCount; //皇后数
int resultCount; //解的个数
int[] queenSite = new int[32];
public static void main(String agrs[])
{
NqueenDigui nqueen = new NqueenDigui();
nqueen.queenCount = 4;
nqueen.queen(0);
}
/*
* 判断是否冲突,如果数组queenSite,有相等的值或者有2值的差等于下标差,则返回true即冲突,
* 否则返回false.表示不冲突,该位置可以放置皇后!
* ...sunpander...08-12-15
*/
public boolean isControl( int n) {
for( int index=0;index
if ((Math.abs(queenSite[n]-queenSite[index]) == Math.abs(n-index))
||( queenSite[n]== queenSite[index]))
return true;
}
return false;
}
public void printResult1()
{
for( int j=0 ;j
System.out.println( "queen["+(j+1)+ "]"+ "="+queenSite[j]);
}
}
/**
* 在控制台显示结果
*/
public void printResult()
{
if(queenCount <= 0)
System.out.println( "无解");
else
{
System.out.println( "第"+resultCount+ "种解法begin:");
for( int k =0;k
System.out.println( "第 "+(k+1)+ " 个皇后位置:"+ "第"+(k+1)+ "行"+ "第"+queenSite[k]+ "列");
}
System.out.println( "end.");
}
}
/*
* 主要函数,从0开始,即把第一个皇后放在第一列!
* 然后把二个放在第一列,如果不冲突,则放置第三个皇后.冲突则放第二列
* 则放置第三个皇后,冲突则放着第二列,再检查是否冲突
* ......
* 如果第n个皇后放置在第n列,仍然冲突,则向上一个皇后返回,放着上一个皇后在它的下一列
*/
public void queen( int nowIndex)
{
if(nowIndex == queenCount)
{
printResult();
}
for( int index = 1;index<=queenCount;index++)
{
queenSite[nowIndex] = index;
if(!isControl(nowIndex))
queen(nowIndex+1);
}
}
}
哎,把代码加到附件,感觉看着不是很方便,,就仍旧粘贴啦,,有点长啦--就这吧,其实都共同学习,,,也不是自己单独得到的答案,所以...if(你路过&&看过)请不啬指教,多多提意见;else 期待你的关注!;;
啊!!!!完工了,呵呵````哦!!说起递归不得不说汉诺塔(用递归很简单,非递归则麻烦)......