1. 程式人生 > >Java——世界名畫陳列館(最少機器人問題)

Java——世界名畫陳列館(最少機器人問題)

問題描述:

世界名畫陳列館問題。世界名畫陳列館由m×n個排列成矩形陣列的陳列室組成。為了防止名畫被盜,需要在陳列室中設定警衛機器人哨位。每個警衛機器人除了監視它所在的陳列室外,還可以監視與它所在的陳列室相鄰的上、下、左、右4
個陳列室。試設計一個安排警衛機器人哨位的演算法,使得名畫陳列館中每一個陳列室都在警衛機器人的監視之下,且所用的警衛機器人數最少。

程式碼

import java.util.Scanner;

/**
 * 世界名畫陳列館問題
 * 最少機器人
 * @author lzq
 *
 */
public class Test {
	static int[][] x=new int[10][10];      //這些陣列大小可以根據自己需要改
	static int[][] y=new int[10][10]; 
	static int[][] bestx=new int[10][10];  //x用來設定當前警衛,y用來表示監控情況,bestx返回最終結果
	static int n, m, best , k=0;

	
	public static void main(String[] args) {
		for(;;) {
		    System.out.println("------------------------------------");
			System.out.println("請設定陳列館區域:");
			System.out.print("m:");
			Scanner sc1 = new Scanner(System.in);
			m = Integer.parseInt(sc1.next());
			System.out.print("n:");
			sc1 = new Scanner(System.in);
			n = Integer.parseInt(sc1.next());
			compute(); //計算
			System.out.println("最少需要"+best+"個警衛!");
			for(int i = 1;i <= n; i++) {
				for(int j = 1;j <= m;j++) {
				   System.out.print(bestx[i][j]+" ");
				}
				System.out.println();
			}
		}
	}
	
	
	/**
	 * 在整個外面加上一圈,便於處理邊界情況
	 */
	public static void compute() {
		best = m*n/3+2;
		for(int i = 0;i <= m+1;i++) {
			y[0][i] = 1;
			y[n+1][i] = 1;
		}
		for(int i = 0;i <= m+1;i++) {
			y[i][0] = 1;
			y[i][m+1] = 1;
		}
		search(1,0);
	}
	
	/**
	 * 在(i, j)處設定一個警衛,並改變其周圍受監控情況
	 * @param i
	 * @param j
	 */
	public static void change(int i,int j) {
		x[i][j] = 1;
		k++;
		y[i][j+1]++;
		y[i+1][j]++;
		y[i][j]++;
		y[i][j-1]++;
		y[i-1][j]++;
	}
	
	/**
	 * 撤銷在(i, j)處設定的警衛,並改變其周圍受監控情況
	 * @param i
	 * @param j
	 */
	public static void restore(int i,int j) {
		x[i][j] = 0;
		k--;
		y[i][j+1]--;
		y[i+1][j]--;
		y[i][j]--;
		y[i][j-1]--;
		y[i-1][j]--;
	}
	
	/**
	 * 回溯搜尋
	 * 從上到下,從左至右搜尋沒被監控的位置
	 * @param i
	 * @param j
	 */
	public static void search(int i,int j) {
		do {
			j++;
			if(j > m) {
				i++;
				j= 1;
			}
		}while(!((y[i][j] == 0) || (i > n)));
		
		//重新整理警衛值
		if(i > n) {
			if(k < best) {
				best = k;
				for(int p = 1;p <= n;p++) 
					for(int q = 1;q <= m;q++) 
						bestx[p][q] = x[p][q];
					return;
				}
			}
		
		if(i < n) {           //結點p
			change(i+1,j);
			search(i,j);      //遞迴搜尋下一個點
			restore(i+1, j);  //恢復
		}
		
		if((y[i][j+1] == 0)) {   //結點q
			change(i,j);
			search(i,j);      
			restore(i, j);
		}
		
		if(((y[i][j+1] == 0) && (y[i][j+2] == 0))) {  //結點q
			change(i,j+1);
			search(i,j);      
			restore(i, j+1);
		}
	}
			
}
		



執行結果:

------------------------------------
請設定陳列館區域:
m:4
n:4
最少需要4個警衛!
0 0 1 0 
1 0 0 0 
0 0 0 1 
0 1 0 0 
------------------------------------
請設定陳列館區域:
m:8
n:6
最少需要11個警衛!
0 0 1 0 0 1 0 0 
1 0 0 0 0 0 0 1 
0 0 0 1 0 0 0 0 
0 1 0 0 0 1 1 0 
0 0 0 0 0 0 0 0 
0 1 0 0 1 0 0 1 
------------------------------------
請設定陳列館區域:
m: