因为 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();
}
}
}