0
点赞
收藏
分享

微信扫一扫

Java、python实现啊哈算法 —— chapter4 深度优先、广度优先(3)

三次方 2022-01-06 阅读 47

这一部分是实现炸弹人游戏,与之前的两个例子大同小异,只是需要注意两点

1. 需要增加一个在某个位置上计算可以消灭敌人数量的方法

2. 由于这个场景中不是求最短路径或者放置纸牌数字,之前的场景中放置完之后需要撤回,因为纸盒放置纸牌允许一个纸盒中放置纸牌后再拿出去,最短路径允许走到一个盒子之后再离开,之后的路径中再次走过这个格子。 而在炸弹人游戏中,目的是求每个格子可以消灭的敌人数量,从而找到最多的那个格子,所以一个格子走过之后就不需要再次走了,因此深度优先的递归之后不需要加撤回的步骤。

下面上代码:

深度优先

java:

import java.util.Scanner;

public class DfsZhaDanRen {
    static int[][] directions = { //定义一个方向数组,分别用来取每个格子的右、下、左、上格子
            {0, 1},
            {1, 0},
            {0, -1},
            {-1, 0}
    };
    static char[][] map = new char[50][50];
    static int[][] book = new int[50][50];
    public static int countEnemy(int x, int y) {
        int count = 0;
        int i = x;
        int j = y;
        while (map[i][j] != '#') { //向右计数,统计向右可以消灭的敌人个数
            if (map[i][j] == 'G') {
                count ++;
            }
            j ++;
        }
        i = x;
        j = y;
        while (map[i][j] != '#') { //向下统计可以消灭的敌人的个数
            if (map[i][j] == 'G') {
                count ++;
            }
            i ++;
        }
        i = x;
        j = y;
        while (map[i][j] != '#') { //向左统计可以消灭的敌人的个数
            if (map[i][j] == 'G') {
                count ++;
            }
            j --;
        }
        i = x;
        j = y;
        while (map[i][j] != '#') { //向上统计可以消灭的敌人的个数
            if (map[i][j] == 'G') {
                count ++;
            }
            i --;
        }
        return count;
    }
    static int maxEnemy = -1;
    static int i;
    static int j;
    public static void dfs(int x, int y) {
        int enemyNum = countEnemy(x, y);
        if (enemyNum > maxEnemy) { //当前位置可以消灭的敌人数如果大于最大值,则改最大值
            maxEnemy = enemyNum;
            i = x;
            j = y;
        }
        for (int i = 0; i < directions.length; i++) { //分别向每个方向深入
            int nextX = x + directions[i][0];
            int nextY = y + directions[i][1];
            if (map[nextX][nextY] == '.' && book[nextX][nextY] == 0) {
                book[nextX][nextY] = 1;
                dfs(nextX, nextY); //下一个位置的格子符合放炸弹规则,从下一格子开始深度优先搜索,注意递归完不需要book[]=0,因为这不是盒子里面放纸牌,放完之后不需要撤回,每个格子走过了就走过了,不需要撤回

            }
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for (int i = 0; i < n; i++) {
            map[i] = sc.next().toCharArray();
        }
        book[3][3] = 1;
        dfs(3, 3);
        System.out.println("最多可消灭敌人" + maxEnemy + "个");
        System.out.println("应该把炸弹放置在" + "(" + i + "," + j + ")" + "处");
    }
}

广度优先:

Java:

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class BfsZhaDanRen {
    static class Site {
        int x;
        int y;
        public Site(int x, int y) { //定义一个位置类
            this.x = x;
            this.y = y;
        }
    }
    static int[][] directions = { //定义一个方向数组,分别用来取每个格子的右、下、左、上格子
            {0, 1},
            {1, 0},
            {0, -1},
            {-1, 0}
    };
    static char[][] map = new char[50][50];
    static int[][] book = new int[50][50];
    public static int countEnemy(int x, int y) {
        int count = 0;
        int i = x;
        int j = y;
        while (map[i][j] != '#') { //向右计数,统计向右可以消灭的敌人个数
            if (map[i][j] == 'G') {
                count ++;
            }
            j ++;
        }
        i = x;
        j = y;
        while (map[i][j] != '#') { //向下统计可以消灭的敌人的个数
            if (map[i][j] == 'G') {
                count ++;
            }
            i ++;
        }
        i = x;
        j = y;
        while (map[i][j] != '#') { //向左统计可以消灭的敌人的个数
            if (map[i][j] == 'G') {
                count ++;
            }
            j --;
        }
        i = x;
        j = y;
        while (map[i][j] != '#') { //向上统计可以消灭的敌人的个数
            if (map[i][j] == 'G') {
                count ++;
            }
            i --;
        }
        return count;
    }

    public static void bfs(int startX, int startY) { //寻找消灭敌人最多的位置的广度优先搜索
        int maxCount = -1; //定义一个变量存储可以消灭的最多的敌人数量
        int resX = 0; //定义两个变量存储消灭敌人最多的点的坐标
        int resY = 0;
        Site startPoint = new Site(startX, startY);
        Queue<Site> queue = new LinkedList<Site>();
        queue.offer(startPoint); //首先把起始位置入队
        while (!queue.isEmpty()) {
            Site site = queue.poll();
            book[site.x][site.y] = 1;
            int enemyNum = countEnemy(site.x, site.y);
            if (enemyNum > maxCount) { //判断当前这一位置是否能消灭最多的敌人
                maxCount = enemyNum;
                resX = site.x;
                resY = site.y;
            }
            for (int[] direction : directions) { //将当前这一点附近四个方向的位置添加到队列中
                int nextX = site.x + direction[0];
                int nextY = site.y + direction[1];
                if (book[nextX][nextY] == 0 && map[nextX][nextY] == '.') {
                    Site nextSite = new Site(nextX, nextY);
                    queue.offer(nextSite);
                }

            }
        }
        System.out.println("最多可以消灭" + maxCount + "个敌人");
        System.out.println("应该将炸弹放置在" + "(" + resX + "," + resY + ")" + "处");
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); //读入行数
        for (int i = 0; i < n; i++) {
            map[i] = sc.next().toCharArray();
        }
        bfs(3, 3);
    }
}
举报

相关推荐

0 条评论