ZOJ 1002 Fire Net

原题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1002

Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, each representing a street or a piece of wall.

A blockhouse is a small castle that has four openings through which to shoot. The four openings are facing North, East, South, and West, respectively. There will be one machine gun shooting through each opening.

Here we assume that a bullet is so powerful that it can run across any distance and destroy a blockhouse on its way. On the other hand, a wall is so strongly built that can stop the bullets.

The goal is to place as many blockhouses in a city as possible so that no two can destroy each other. A configuration of blockhouses is legal provided that no two blockhouses are on the same horizontal row or vertical column in a map unless there is at least one wall separating them. In this problem we will consider small square cities (at most 4x4) that contain walls through which bullets cannot run through.

The following image shows five pictures of the same board. The first picture is the empty board, the second and third pictures show legal configurations, and the fourth and fifth pictures show illegal configurations. For this board, the maximum number of blockhouses in a legal configuration is 5; the second picture shows one way to do it, but there are several other ways.

Your task is to write a program that, given a description of a map, calculates the maximum number of blockhouses that can be placed in the city in a legal configuration.

The input file contains one or more map descriptions, followed by a line containing the number 0 that signals the end of the file. Each map description begins with a line containing a positive integer n that is the size of the city; n will be at most 4. The next n lines each describe one row of the map, with a '. ' indicating an open space and an uppercase 'X ' indicating a wall. There are no spaces in the input file.

For each test case, output one line containing the maximum number of blockhouses that can be placed in the city in a legal configuration.

Sample input:

4

.X..

....

XX..

....

Sample output:

5

 

题目解析:

我这里仅仅给出了一对测试数据,好吧。

题目其实啰嗦的很,看的心烦。

就是一个MxM的矩阵里

黑块填充的是墙壁,其余的是空白。

要你往空白地方填充碉堡(看到那个圆的没,那就是碉堡)

碉堡当然会发出子弹了但是只能横的和竖的。。不能穿过墙壁。

OK,题目问你,放置方案,可以覆盖全部地图空白块(不是五子棋,不能放在交叉线上)

 

思路:

我思路一向奇葩,不理解就算了。1002毕竟是入门题目。

举例一个缩小版的模型。

。。

。X           《---------

其实每个点,都有两种情况,放和不放,当然,墙上是不可以放的。

程序会逐个点进行判断该不该放置。

先计算在0,0放置了以后,0,0点之后,能放几个

然后计算0,0点如果不放置,能放几个,然后决定放置还是不放置

其实就是。。DP(动态规划)。。。好吧,我相信你懂得

然后就是那个状态转移公式,我也不记得那个公式长什么样了,其实没关系,好吧。。

下面是程序

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class Main{

    private static int M = 0;
    private static int BLANK = 0;
    private static int WALL = 1;
    private static int BLOCKBUILDING = 2;
    private static int COVER = 3;
    private static Cell[][] grid = null;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()) {
            int size = in.nextInt();
            if (size == 0) {
                return;
            }
            //the size of grid
            M = size;
            init();
            in.nextLine();
            //initialize the wall in grid.....
            for (int j = 0; j < size; j++) {
                String str = in.nextLine();
                char[] chars = str.toCharArray();
                for (int k = 0; k < chars.length; k++) {
                    if (chars[k] == 'X') {
                        grid[j][k].setStatus(WALL);
                    }
                }
            }
            System.out.println(maxBlockHouse());
        }
    }

    private static int maxBlockHouse() {
        //show the graph......
        Position p = new Position();
        p.setX(0);
        p.setY(0);
        List<Position> list = maxBlockHouse(p);
        return list.size();
    }

    private static void clearAllCover() {
        for (int i = 0; i < M; i++) {
            for (int k = 0; k < M; k++) {
                if (!(grid[i][k].getStatus() == WALL)) {
                    grid[i][k].setStatus(BLANK);
                }
            }
        }
    }

    private static List<Position> maxBlockHouse(Position p) {
        // find the next position of a point......
        Position nextP = nextPosition(p);
        boolean last = false;
        if (nextP == null) {
            last = true;
        }

        // if current point can not be set
        if (!checkPosition(p)) {
            // if the check is not pass,just go to next
            if (!last) {
                return maxBlockHouse(nextP);
            } else {
                // if it is the last and can not be set
                return new LinkedList<Position>();
            }
        }

        // if the current point can be set, we have to choose set or not set
        
        if (last) {
            // if it is the last position and can be choose
            List<Position> list = new LinkedList<Position>();
            list.add(p);
            return list;
        }

        // if set the current position
        int[][] currentStatus = recordStatus();
        markPosition(p);
        List<Position> chooseList = maxBlockHouse(nextP);
        chooseList.add(p);
        // recover the list
        recover(currentStatus);
        List<Position> notChooseList = maxBlockHouse(nextP);
        recover(currentStatus);
        return chooseList.size() > notChooseList.size() ? chooseList : notChooseList;
    }

    private static int[][] recordStatus() {
        int[][] status = new int[M][M];
        for(int i=0;i<M;i++)
            for(int j=0;j<M;j++){
                status[i][j] = grid[i][j].getStatus();
            }
        return status;
    }

    private static Position nextPosition(Position p) {
        if (p.getX() == M - 1 && p.getY() == M - 1) {
            // that is the end
            return null;
        } else if (p.getX() == M - 1) {
            Position newP = new Position();
            // return to 0
            newP.setX(0);
            newP.setY(p.getY() + 1);
            return newP;
        } else {
            Position newP = new Position();
            // return to 0
            newP.setX(p.getX() + 1);
            newP.setY(p.getY());
            return newP;
        }
    }

    private static void init() {
        grid = new Cell[M][M];
        for (int i = 0; i < M; i++) {
            for (int k = 0; k < M; k++) {
                grid[i][k] = new Cell();
            }
        }
    }

    private static boolean checkPosition(Position p) {
        if (grid[p.getY()][p.getX()].getStatus() == BLANK) {
            // only the status is blank is ok to set
            return true;
        }
        return false;
    }

    private static void markPosition(Position p) {
        // look for 4 direction....
        // put a block house
        grid[p.getY()][p.getX()].setStatus(BLOCKBUILDING);
        //up
        for (int i = p.getY() - 1; i >= 0; i--) {
            if (grid[i][p.getX()].getStatus() == BLANK) {
                // it is blank,set to cover
                grid[i][p.getX()].setStatus(COVER);
            } else if (grid[i][p.getX()].getStatus() == COVER) {
                // if it is continue, just skip
                continue;
            } else if (grid[i][p.getX()].getStatus() == WALL) {
                // if it is wall stop
                break;
            }
        }
        // down
        for (int i = p.getY() + 1; i < M; i++) {
            if (grid[i][p.getX()].getStatus() == BLANK) {
                // it is blank,set to cover
                grid[i][p.getX()].setStatus(COVER);
            } else if (grid[i][p.getX()].getStatus() == COVER) {
                // if it is continue, just skip
                continue;
            } else if (grid[i][p.getX()].getStatus() == WALL) {
                // if it is wall stop
                break;
            }
        }
        // left
        for (int i = p.getX() - 1; i >= 0; i--) {
            if (grid[p.getY()][i].getStatus() == BLANK) {
                // it is blank,set to cover
                grid[p.getY()][i].setStatus(COVER);
            } else if (grid[p.getY()][i].getStatus() == COVER) {
                // if it is continue, just skip
                continue;
            } else if (grid[p.getY()][i].getStatus() == WALL) {
                // if it is wall stop
                break;
            }
        }
        // right
        for (int i = p.getX() + 1; i < M; i++) {
            if (grid[p.getY()][i].getStatus() == BLANK) {
                // it is blank,set to cover
                grid[p.getY()][i].setStatus(COVER);
            } else if (grid[p.getY()][i].getStatus() == COVER) {
                // if it is continue, just skip
                continue;
            } else if (grid[p.getY()][i].getStatus() == WALL) {
                // if it is wall stop
                break;
            }
        }
    }

    private static void recover(int[][] status) {
        for(int i=0;i<M;i++)
            for(int j=0;j<M;j++){
                grid[i][j].setStatus(status[i][j]);
            }
    }

    private static void showGraph() {
        for (int i = 0; i < M; i++) {
            for (int k = 0; k < M; k++) {
                if (grid[i][k].getStatus() == BLANK) {
                    System.out.print(". ");
                } else if (grid[i][k].getStatus() == WALL) {
                    System.out.print("W ");
                } else if (grid[i][k].getStatus() == BLOCKBUILDING) {
                    System.out.print("B ");
                } else {
                    System.out.print("C ");
                }
            }
            System.out.println("");
        }
    }

    private static class Cell {
        private int status = BLANK;

        public int getStatus() {
            return status;
        }

        public void setStatus(int status) {
            this.status = status;
        }
    }

    private static class Position {
        private int x;

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

        private int y;

        @Override
        public String toString() {
            return y + "," + x;
        }
    }
}

 公司不能打中文。。。程序是英文的。。将就下看吧。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值