1. 程式人生 > >java求微信最強連一連(方法:遞歸回溯遍歷)

java求微信最強連一連(方法:遞歸回溯遍歷)

package my_mian_shi;



/**
 * 
 * 
 * 
 * @author Administrator
 *
 */
public class GameMain {
	
	class TwoInteger{
		public Integer column;
		public Integer row;
	}
	
	Integer column;   //列
	Integer row;   //行
	int []notExistPot;  //不能存在的點
	boolean [][] passedPot; //已經經過的點(以二維的方式表示某個方格)
	Integer []path; //點的路徑( 每一個數值表示 從左到右、從上到下、從0開始、給方塊編號 )
	TwoInteger ti = new TwoInteger();//用於進行一維轉二維
	
	
 	public GameMain(Integer row,Integer column,int []notEP){
 		
 		this.notExistPot=notEP;
 	 
 		if(column != null && column>0 && row != null && row > 0)
 		{
 			this.column=column;
 	 		this.row=row;
 			passedPot =new boolean[row][column];
 			path = new Integer[row*column-notExistPot.length];
 		}else {
 			throw new RuntimeException("列或行出現問題");
 		}
 
 	}
 	
 	//判斷為單一邊界
 	public boolean decideSingleBounds(int bounds,int singleBounds) {
 		if((bounds & singleBounds)==0) return false;
 		else return true;
 	}
 	
 	//設定passedPot和path
 	public void setPassedPotAndPath(int p,int a, boolean b) {
 		path[p]=a;//入口
	 	setPassedPot(a, b);
 	}
 	
 	//設定passedPot和path
 	public void setPassedPotAndPath(int p,int a) {
 		path[p]=a;//入口
	 	setPassedPot(a, true);
 	}
 	
	//判斷是否在邊界(組合) 
 	public int decideBounds(int row ,int column) {
 		int count=0;
 		if(row==0) count += 1;//上邊界
 		else if(row==this.row-1) count += 2; // 下邊界
 		else if(column==0) count += 4; //左邊界
 		else if(column==this.column-1) count += 8; //右邊界 
 		return count; 
 	}
 	
 	//判斷是否在邊界(組合)
 	public int decideBounds(int pot) {
 		int count=0;
 		if (pot<column) count += 1;
 		if ((pot-(row-1)*column)>=0 && (pot-(row-1)*column)<column) count += 2;
 		if (pot%column==0) count += 4;
 		if (pot%column==column-1) return count += 8;
 		return count;
 	}
 	
 	//判斷一維到二維陣列是否越界
 	public boolean passedPotIndexOutOfBounds(int a) {
 		return a<0 || a>=column*row;
 	}
 	
 	//判斷多個數是否存在越界
 	public boolean passedPotIndexOutOfBounds(int []a) {
 		for(int i:a) 
 			if(passedPotIndexOutOfBounds(i))
 				return true;
 		return false;
 	}
 	
 	//二維轉一維
 	public int twoToOne(int row,int column) {
 		return (row)*this.column+column;
 	}
 	
 	//一維轉二維
 	public void oneToTwo(int pot) {
 		int a=((pot+1)%column)-1;
 		ti.column = (a == -1) ? column-1 : a;
 		ti.row = pot/column;
 		//System.out.println(ti.row+" "+ti.column);
 	}
 	
	//列印路徑
	public void showPath() {
		for(int i=0;i<path.length;i++) {
			System.out.print(path[i]+" ");
		}
	}
	
	
	//判斷點是否存在
	public boolean notExistPot(Integer pot) {
		for(int i=0;i<notExistPot.length;i++) {
			if(pot==notExistPot[i])
				return true;
		}
		return false;
	}
	
	
	//點是否已經被經過
	public boolean passedPot(Integer pot) {
		oneToTwo(pot);
		return this.passedPot[ti.row][ti.column];
	}
	
	//判斷點是否是不存在的點或者已經過的點
	public boolean passedPotOrNotExistPot(int a) {
		return this.notExistPot(a) || this.passedPot(a);
	}
	
	
	// 回溯法遍歷 哈密頓通路 的一個解
	public void run(int nowPosition){
		boolean flag=false;
		int a = path[nowPosition];
		if (nowPosition==this.path.length-1) {
			this.showPath();
			System.exit(0);
		}
		//左邊是否可以走
		if (!this.decideSingleBounds(this.decideBounds(a), 4) //不能在左邊界
				&&!this.passedPotIndexOutOfBounds(a-1)  //不能越界
				&& !this.passedPotOrNotExistPot(a-1)    //不能是已經經過的點和不能是不存在的點
		) {
			this.setPassedPotAndPath(nowPosition+1,a-1);
			run(nowPosition+1);
			flag=true;
		}
		if(flag) {
			setPassedPot(a-1,false);
			flag=false;
		}
		//右邊是否可以走
		if(!this.decideSingleBounds(this.decideBounds(a), 8)
				&&!this.passedPotIndexOutOfBounds(a+1) 
				&& !this.passedPotOrNotExistPot(a+1)) {
			this.setPassedPotAndPath(nowPosition+1,a+1);
			run(nowPosition+1);
			flag=true;
		}
		if(flag) {
			setPassedPot(a+1,false);
			flag=false;
		}
		//上邊是否可以走
		if(!this.decideSingleBounds(this.decideBounds(a), 1)
				&&!this.passedPotIndexOutOfBounds(a-column)  
				&& !this.passedPotOrNotExistPot(a-column)) {
			this.setPassedPotAndPath(nowPosition+1,a-column);
			run(nowPosition+1);
			flag=true;
		}
		if(flag) {
			setPassedPot(a-column,false);
			flag=false;
		}
		//下邊是否可以走
		if(!this.decideSingleBounds(this.decideBounds(a), 2)
				&&!this.passedPotIndexOutOfBounds(a+column)
				&& !this.passedPotOrNotExistPot(a+column)) {
			this.setPassedPotAndPath(nowPosition+1,a+column);
			run(nowPosition+1);
			flag=true;
		}
		if(flag) {
			setPassedPot(a+column,false);
			flag=false;
		}
		
	}
	
	//設定PassedPot的值
	public void setPassedPot(int a, boolean b) {
		this.oneToTwo(a);
		this.passedPot[ti.row][ti.column]=b;
	}

	public static void main(String[] args) {
	 	GameMain gm = new GameMain(9,7,new int[] {4,5,6,11,18,43,56}) ; 
	 	

	 	/*
	 	for(int i=0;i<30;i++) {
	 		System.out.print(i+" ");
	 		gm.oneToTwo(i); // 測試一維轉二維
	 	}
	 	*/
	 	/*
	 	for(int i=0;i<30;i++) {
	 		System.out.print(i+" ");
	 		System.out.println(gm.decideBounds(i));//測試邊界範圍是否正確
	 	}
	 	*/
	 	/*
	 	for(int i=1;i<16;i++) { //測試將組合邊界轉化為單邊界
	 		System.out.print(gm.decideSingleBounds(i, 1)+" ");
	 		System.out.print(gm.decideSingleBounds(i, 2)+" ");
	 		System.out.print(gm.decideSingleBounds(i, 4)+" ");
	 		System.out.print(gm.decideSingleBounds(i, 8)+" ");
	 		System.out.println();
	 	}
	 	*/
	 	/*
	 	for(int i=0;i<5;i++)
	 		for(int j=0;j<6;j++) {
	 			System.out.print(gm.twoToOne(i, j) +" ");
	 		}
	 	*/
	 	gm.setPassedPotAndPath(0, 33);//設定入口
	 	gm.run(0);
	}
}