因爲 N <= 4,所以算法選擇了回溯(暴搜= =)。
實現則是用了遞歸(迭代次數不會太深)。
從左上角開始依次枚舉每一個點,尋找空地(即未被佔用 / 未被火力封鎖)
1. 找到後,此點設爲fire,然後依次掃描四個方向直線上的點,並設置爲“不可用",遇到牆或者邊界則停止該方向掃描。(此處用了一個辦法是,wall & fire 的值都小於0,空地的值爲0,當空地被掃描到的時候,值+1,這樣的話,當需要去掉這個fire點的時候(恢復現場),只需要重做上述操作,值-1。這樣避免了在恢復現場的時候,不會影響到其他點對某塊空地的封鎖)
掃描完畢之後,遞歸進行第二次搜索。
遞歸返回後,恢復現場。
2. 忽略此點,直接尋找下一個空地(即for循環繼續)
Java複習
1. 靜態成員變量/類變量 static int a這樣的變量在這個類的所有對象裏只有一個,這個類的所有對象“共享”同一個類變量。
2. 常量
static final int a = 5;
3. 數組
static int[][] a; //申明時不能定義長度
Code:
import java.io.*;
import java.util.Scanner;
public class ZOJ1002 {
static int[][] a; //0_space -1_wall -2_fire >0_non-avai
static int m = 0;
static final int[][] d = {{1,0},{-1,0},{0,1},{0,-1}};
public static int search(int x, int y, int k) throws IOException {
int i, j, h, now = 0, max = k;
for (i = x; i < m; i++) {
for (j = y; j < m; j++) {
if (a[i][j] == 0) {
//occupy this point
a[i][j] = -2;
for (h = 0; h < 4; h++) {
int xx = i+d[h][0], yy = j+d[h][1];
while (xx>=0 & xx<m & yy>=0 & yy<m) {
if (a[xx][yy] >= 0)
a[xx][yy]++;
else if (a[xx][yy] == -1)
break;
xx = xx+d[h][0];
yy = yy+d[h][1];
}
}
if (max < k+1)
max = k+1;
// search next point with occupied this point
now = search(0,0,k+1);
if (max < now)
max = now;
//Recover
a[i][j] = 0;
for (h = 0; h < 4; h++) {
int xx = i+d[h][0], yy = j+d[h][1];
while (xx>=0 & xx<m & yy>=0 & yy<m) {
if (a[xx][yy] > 0)
a[xx][yy]--;
else if (a[xx][yy] == -1)
break;
xx = xx+d[h][0];
yy = yy+d[h][1];
}
}
//non occupied
}
}
}
return max;
}
public static void main(String[] args) throws IOException {
int i,j,max = 0,k;
String line;
Scanner in = new Scanner (System.in);
m = in.nextInt();
in.nextLine();
while (m != 0) {
//Input
a = new int[m][m];
for (i = 0; i < m; i++) {
line = in.nextLine();
for (j = 0; j < m; j++) {
if (line.charAt(j) == '.')
a[i][j] = 0;
else
a[i][j] = -1;
}
}
System.out.println(search(0,0,0));
//Next one
m = in.nextInt();
in.nextLine();
}
}
}