[题解] ZOJ1002 -- Fire Net

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值