藍橋杯-算法提高(回溯-遞歸):王、後傳說

問題描述:

問題描述

  地球人都知道,在國際象棋中,後如同太陽,光芒四射,威風八面,它能控制橫、堅、斜線位置。
  看過清宮戲的中國人都知道,後宮乃步步驚心的險惡之地。各皇后都有自己的勢力範圍,但也總能找到相安無事的辦法。
  所有中國人都知道,皇權神聖,伴君如伴虎,觸龍顏者死......
  現在有一個n*n的皇宮,國王佔據他所在位置及周圍的共9個格子,這些格子皇后不能使用(如果國王在王宮的邊上,佔用的格子可能不到9個)。當然,皇后也不會攻擊國王。
  現在知道了國王的位置(x,y)(國王位於第x行第y列,x,y的起始行和列爲1),請問,有多少種方案放置n個皇后,使她們不能互相攻擊。

輸入格式

  一行,三個整數,皇宮的規模及表示國王的位置

輸出格式

  一個整數,表示放置n個皇后的方案數

樣例輸入

8 2 2

樣例輸出

10

數據規模和約定

  n<=12

 

問題分析:

王后傳說的問題其實就是在八皇后問題之上添加了國王附近位置不能佔用的條件,基本解題思路和八皇后問題一樣。

首先我們來看一下八皇后問題:

八皇后問題,是一個古老而著名的問題,是回溯算法的典型案例。該問題是國際西洋棋棋手馬克斯·貝瑟爾於1848年提出:在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。 高斯認爲有76種方案。1854年在柏林的象棋雜誌上不同的作者發表了40種不同的解,後來有人用圖論的方法解出92種結果。計算機發明後,有多種計算機語言可以解決此問題。

解決八皇后的問題關鍵在於尋找八個皇后之間不相容的位置關係,當不滿足互斥條件時可以將皇后放入棋盤中。國王王后問題只需要在最後再來判斷王后的位置與國王的位置是否衝突。分成兩步來做比較清晰。

下面給大家看一下我得出的國王和王后互斥關係式

國王王后關係式
國王王后互斥關係

 

解題步驟:

1.從第一個皇后開始擺放,從0行0開始放(0,0),判斷與當前皇后之前的皇后位置是否衝突。如果不衝突則擺放下一個皇后,否則從第一行下一個位置開始放(0,1)。(遞歸體)

2.重複第一個步驟直到所有的皇后都擺放完,即先解決了皇后是否能在棋盤裏放完,否則連皇后都解決不了就更別提國王了。

3.當所有的皇后都擺放完了之後,判斷每一個皇后的位置與國王的位置是否衝突。否則該擺放方法不可取(遞歸出口)

詳細代碼:

package kingQueen;
import java.util.Scanner;

public class Main {
	static int n = 0;
	static int x_king = 0, y_king = 0;
	static int queen[] = new int [12];
	static int result = 0;
	
	public static void main(String args[]) {
		
		
		@SuppressWarnings("resource")
		Scanner input = new Scanner(System.in);
		n = input.nextInt();
		//座標從0開始,國王座標需要減一
		x_king = input.nextInt() - 1;
		y_king = input.nextInt() - 1;
		find(0);
		System.out.println(result);
		
		
	}
	
	public static  void find(int position) {
		
		//放置完王后後判斷是否與國王位置衝突
		if(position == n) {
			boolean conflict_king = false;
			for(int i = 0;i<n;i++) 
				//位置衝突
				if(i >= x_king - 1 && i<= x_king + 1 && queen[i] >= y_king - 1 && queen[i] <= y_king + 1) {
					conflict_king = true;
					break;
				}
			if(conflict_king == false) {
				result++;
				return;
			}
				
			
		}
		//放置皇后位置,每個皇后默認在不同的行
		for(int i = 0;i<n;i++) {
			
			int j =0;
			boolean conflict_queen = false;
			for(;j<position;j++) 
				//皇后位置衝突
				if(i == queen[j] || Math.abs(i - queen[j]) == Math.abs(position - j)) {
					conflict_queen = true;
					break;
				}
					
			if(conflict_queen == false) {
				queen[position] = i;
				find(position+1);
			}
			
			
		}
		
		
	}

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章