Java玩转《啊哈算法》暴力枚举之炸弹人

当一个人身强力壮、洋溢着青春气息的时候,要做到坚强是比较简单和容易的。只有当生活像铁环一样把你紧紧箍住的时候,能做到坚强才是光荣的。

有目录,不迷路

  • 缘起
  • 代码地址
  • 炸弹人
  • 问题

缘起

各位小伙伴们好呀!本人最近看了下《啊哈算法》,写的确实不错。

但稍显遗憾的是,书籍示例代码是c语言,而不是本人常用的Java。

那就弥补遗憾,说干就干,把这本书的示例语言用java写一遍, 顺带附上一些自己的理解!

今天我们来用枚举的思想玩一个炸弹人的游戏!
在这里插入图片描述

来不及买纸质书但又想尽快感受算法魅力的童鞋也甭担心,电子版的下载链接已经放到下方了,可尽情下载。

链接:https://pan.baidu.com/s/1imxiElcCorw2F-HJEnB-PA?pwd=jmgs
提取码:jmgs

代码地址

本文代码已开源:

git clone https://gitee.com/guqueyue/my-blog-demo.git

请切换到gitee分支,

然后查看aHaAlgorithm模块下的src/main/java/com/guqueyue/aHaAlgorithm/chapter_3_Enum即可!

炸弹人

说起炸弹人,大家可能想到的是英雄联盟游戏里面的爆破鬼才 — 吉格斯。

在这里插入图片描述

不过这里说的是小霸王游戏机里面的“炸弹人”游戏,一听就有点年代感了。

在这里插入图片描述

现在有一个特殊的关卡如下。你只有一枚炸弹,但是这枚炸弹威力超强(杀伤距离超长,可以消灭杀伤范围内所有的敌人)。
请问在哪里放置炸弹才可以消灭最多的敌人呢?

在这里插入图片描述
那么,我们要怎么用代码来计算这个问题呢?

首先,我们要将图形化的地图进行模型化处理,我们用 # 来表示墙壁、 G表示敌人,.表示空地,

其中炸弹只能放在空地上,爆炸范围为上、下、左、右四个范围,并且不能穿墙。

char[][] arr  = {{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '#', 'G', 'G', 'G', '.', '#'},{'#', '#', '#', '.', '#', 'G', '#', 'G', '#', 'G', '#', 'G', '#'},{'#', '.', '.', '.', '.', '.', '.', '.', '#', '.', '.', 'G', '#'},{'#', 'G', '#', '.', '#', '#', '#', '.', '#', 'G', '#', 'G', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '.', '#', '.', 'G', 'G', '#'},{'#', 'G', '#', '.', '#', 'G', '#', '.', '#', '.', '#', '#', '#'},{'#', '#', 'G', '.', '.', '.', 'G', '.', '.', '.', '.', '.', '#'},{'#', 'G', '#', '.', '#', 'G', '#', '#', '#', '.', '#', 'G', '#'},{'#', '.', '.', '.', 'G', '#', 'G', 'G', 'G', '.', 'G', 'G', '#'},{'#', 'G', '#', '.', '#', 'G', '#', 'G', '#', '.', '#', 'G', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '#', 'G', '.', 'G', 'G', '#'},{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'}
};

那么,初始化地图之后,我们要怎么利用枚举的思想来解决这个问题呢?

很简单,暴力就好了。我们直接遍历每个点,计算每个点可以消灭敌人的个数就好了。

如果遇到可以消灭敌人更多数的点,就把它的坐标和可消灭敌人数记录下来。

在这里插入图片描述
至于如何计算每个点可以消灭敌人的个数,写四个循环分别往四个方向计算就好了。例如,求上方的可消灭敌人数:

 int sum = 0, x = i, y = j; // sum: 当前坐标可消灭敌人数,x: 当前横坐标,y: 当前纵坐标// 向上找while (arr[x][y] != '#' && x >= 0 && x < w) { // 四周一定有墙,所以 坐标是否越界其实不用判断if (arr[x][y] == 'G') {sum++;}x--;}

因为我们这里是向上,所以用x--,其他方向如下图所示:
在这里插入图片描述

完整代码如下:

package com.guqueyue.aHaAlgorithm.chapter_3_Enum;/*** @Author: guqueyue* @Description: 炸弹人* @Date: 2024/1/17**/
public class BomberMan {public static void main(String[] args) {char[][] arr  = {{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '#', 'G', 'G', 'G', '.', '#'},{'#', '#', '#', '.', '#', 'G', '#', 'G', '#', 'G', '#', 'G', '#'},{'#', '.', '.', '.', '.', '.', '.', '.', '#', '.', '.', 'G', '#'},{'#', 'G', '#', '.', '#', '#', '#', '.', '#', 'G', '#', 'G', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '.', '#', '.', 'G', 'G', '#'},{'#', 'G', '#', '.', '#', 'G', '#', '.', '#', '.', '#', '#', '#'},{'#', '#', 'G', '.', '.', '.', 'G', '.', '.', '.', '.', '.', '#'},{'#', 'G', '#', '.', '#', 'G', '#', '#', '#', '.', '#', 'G', '#'},{'#', '.', '.', '.', 'G', '#', 'G', 'G', 'G', '.', 'G', 'G', '#'},{'#', 'G', '#', '.', '#', 'G', '#', 'G', '#', '.', '#', 'G', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '#', 'G', '.', 'G', 'G', '#'},{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'}};// maxSum: 最大可消灭敌人数,maxX: 最大可消灭敌人数的横坐标,maxY: 最大可消灭敌人数的纵坐标, w: 矩阵宽度,h: 矩阵高度int maxSum = 0, maxX = -1, maxY = -1, w = arr.length, h = arr[0].length;for (int i = 0; i < w; i++) {for (int j = 0; j < h; j++) {// 空地才可以防止炸弹if(arr[i][j] != '.') {continue;}int sum = 0, x = i, y = j; // sum: 当前坐标可消灭敌人数,x: 当前横坐标,y: 当前纵坐标// 向上找while (arr[x][y] != '#' && x >= 0 && x < w) { // 四周一定有墙,所以 坐标是否越界其实不用判断if (arr[x][y] == 'G') {sum++;}x--;}// 向下找x = i;y = j;while (arr[x][y] != '#' && x >= 0 && x < w) {if (arr[x][y] == 'G') {sum++;}x++;}// 向左找x = i;y = j;while (arr[x][y] != '#' && y >= 0 && y < h) {if (arr[x][y] == 'G') {sum++;}y--;}// 向右找x = i;y = j;while (arr[x][y] != '#' && y >= 0 && y < h) {if (arr[x][y] == 'G') {sum++;}y++;}if (sum > maxSum) {maxX = i;maxY = j;maxSum = sum;}}}System.out.printf("在(%d, %d)处放置炸弹,杀伤的敌人最多,为%d人\n", maxX, maxY, maxSum);}
}

运行,得:

在这里插入图片描述

问题

上文的代码虽然偏长,但是思路是不是很简单顺畅?

但是正如作者所说,枚举的思想虽然简单粗暴,但是不够智能:
在这里插入图片描述
如,我们像作者一样更改地图:

package com.guqueyue.aHaAlgorithm.chapter_3_Enum;/*** @Author: guqueyue* @Description: 炸弹人* @Date: 2024/1/17**/
public class BomberMan {public static void main(String[] args) {char[][] arr  = {{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '#', 'G', 'G', 'G', '.', '#'},{'#', '#', '#', '.', '#', 'G', '#', 'G', '#', 'G', '#', 'G', '#'},{'#', '.', '.', '.', '.', '.', '.', '.', '#', '.', '.', 'G', '#'},{'#', 'G', '#', '.', '#', '#', '#', '.', '#', 'G', '#', 'G', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '.', '#', '.', 'G', 'G', '#'},{'#', 'G', '#', '.', '#', 'G', '#', '.', '#', '.', '#', '#', '#'},{'#', '#', 'G', '.', '.', '.', 'G', '.', '.', '.', '.', '.', '#'},{'#', 'G', '#', '.', '#', 'G', '#', '#', '#', '.', '#', 'G', '#'},{'#', '.', '.', '.', 'G', '#', 'G', 'G', 'G', '.', 'G', 'G', '#'},{'#', 'G', '#', '.', '#', 'G', '#', 'G', '#', '.', '#', 'G', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '#', 'G', '.', 'G', 'G', '#'},{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'}};arr = new char[][]{{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '#', 'G', 'G', 'G', '.', '#'},{'#', '#', '#', '.', '#', 'G', '#', 'G', '#', 'G', '#', 'G', '#'},{'#', '.', '.', '.', '.', '.', '.', '.', '#', '.', '.', 'G', '#'},{'#', 'G', '#', '.', '#', '#', '#', '.', '#', 'G', '#', 'G', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '.', '#', '.', 'G', 'G', '#'},{'#', 'G', '#', '.', '#', 'G', '#', '.', '#', '.', '#', '.', '#'},{'#', '#', 'G', '.', '.', '.', 'G', '.', '.', '.', '.', '.', '#'},{'#', 'G', '#', '.', '#', 'G', '#', '#', '#', '.', '#', 'G', '#'},{'#', '.', '.', '.', 'G', '#', 'G', 'G', 'G', '.', 'G', 'G', '#'},{'#', 'G', '#', '.', '#', 'G', '#', 'G', '#', '.', '#', 'G', '#'},{'#', 'G', 'G', '.', 'G', 'G', 'G', '#', 'G', '.', 'G', 'G', '#'},{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'}};// maxSum: 最大可消灭敌人数,maxX: 最大可消灭敌人数的横坐标,maxY: 最大可消灭敌人数的纵坐标, w: 矩阵宽度,h: 矩阵高度int maxSum = 0, maxX = -1, maxY = -1, w = arr.length, h = arr[0].length;for (int i = 0; i < w; i++) {for (int j = 0; j < h; j++) {// 空地才可以防止炸弹if(arr[i][j] != '.') {continue;}int sum = 0, x = i, y = j; // sum: 当前坐标可消灭敌人数,x: 当前横坐标,y: 当前纵坐标// 向上找while (arr[x][y] != '#' && x >= 0 && x < w) { // 四周一定有墙,所以 坐标是否越界其实不用判断if (arr[x][y] == 'G') {sum++;}x--;}// 向下找x = i;y = j;while (arr[x][y] != '#' && x >= 0 && x < w) {if (arr[x][y] == 'G') {sum++;}x++;}// 向左找x = i;y = j;while (arr[x][y] != '#' && y >= 0 && y < h) {if (arr[x][y] == 'G') {sum++;}y--;}// 向右找x = i;y = j;while (arr[x][y] != '#' && y >= 0 && y < h) {if (arr[x][y] == 'G') {sum++;}y++;}if (sum > maxSum) {maxX = i;maxY = j;maxSum = sum;}}}System.out.printf("在(%d, %d)处放置炸弹,杀伤的敌人最多,为%d人\n", maxX, maxY, maxSum);}
}

在这里插入图片描述
运行,得:

在这里插入图片描述

但是,很明显 (1, 11) 小人根本走不进去:

在这里插入图片描述
所以,这个答案是错误的,我们使用枚举的思想根本无法判断哪片空地小人是否可以到达。

那,怎么办呢?不要着急,我们在后期的博客中讲《万能的搜索》时,再来解决这个问题!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/499404.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用Docker部署IT-Tools并结合内网穿透实现公网访问本地工具箱服务

作为程序员&#xff0c;在日常工作中&#xff0c;需要借助一些工具来提高我们工作效率&#xff0c;IT-Tools是为开发人员度身打造的一套便捷在线工具。它提供全面功能&#xff0c;使开发者能以更高效方式完成任务。经由IT-Tools&#xff0c;开发人员能轻松应对各类技术挑战&…

Linux网络编程(四-TCP协议)

目录 一、TCP概念 二、TCP的首部格式 三、TCP可靠传输机制 3.1 确认应答机制 3.2 超时重传机制 3.3 连接管理 3.3.1 三次握手 3.3.2 四次挥手 3.4 流量控制 3.5 拥塞控制 四、TCP效率机制 4.1 滑动窗口 4.2 重发控制 4.3 延迟应答 4.4 捎带应答 五、TCP的…

利用观测云实现 Kubernetes 多集群可观测

简介 观测云的工作空间接入多个 Kubernetes 集群时&#xff0c;是如何区分不同集群&#xff0c;达到多集群的可观测性&#xff1f; 增加Tag NAMESPACE&#xff1a;DataKit 选举空间&#xff0c;需要设置 ENV_NAMESPACE 环境变量&#xff0c;值为非空字符&#xff0c;不同集群…

第三百七十回

文章目录 1. 概念介绍2. 使用方法2.1 获取所有时区2.2 转换时区时间 3. 示例代码4. 内容总结 我们在上一章回中介绍了"分享一些好的Flutter站点"相关的内容&#xff0c;本章回中将介绍timezone包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在…

力扣递归:路径总和

思路&#xff1a;此题思路为递归实现&#xff0c;递归思路为&#xff1a;在每层递归的过程中将各个节点的数据记录下来&#xff0c;不断将减少目标数据的值准备进行判断&#xff0c;当进行到叶子节点时要进行判断 /*** Definition for a binary tree node.* struct TreeNode {…

服务式办公室联合办公空间,傻傻分不清楚

服务式办公室是一种灵活的办公解决方案&#xff0c;适合各种规模和类型的企业&#xff0c;尤其是那些寻求成本效益和灵活租赁条件的新兴企业。以下是服务式办公室的主要使用者和设施特点&#xff1a; 谁会使用服务式办公室&#xff1f; 新兴初创企业&#xff1a;由于初创企业在…

面试笔记系列四之SpringBoot+SpringCloud+计算机网络基础知识点整理及常见面试题

目录 Spring Boot 什么是 Spring Boot&#xff1f; Spring Boot 有哪些优点&#xff1f; SpringBootApplication注解 Spring Boot 的启动流程 Spring Boot属性加载顺序 springboot自动配置原理是什么&#xff1f;&#xff08;*&#xff09; 如何理解springboot中的start…

Leetcode—64. 最小路径和【中等】

2024每日刷题&#xff08;116&#xff09; Leetcode—64. 最小路径和 实现代码 class Solution { public:int minPathSum(vector<vector<int>>& grid) {int m grid.size();int n grid[0].size();vector<vector<int>> dp(m 1, vector<int&g…

配电房智能辅助监控系统设计

业务背景 工业企业、学校、医院、居民小区等单位有这海量的配电房&#xff0c;这些配电房内的配电设备种类多、运行环境复杂&#xff0c;存在各种各样的安全隐患。目前这些配电房主要依靠人员在场值守或巡检方式进行管理&#xff0c;但单纯的人工运维方式既成本高&#xff0c;…

pycharm基本操作,零基础快速上手

新建项目 pycharm安装完成后&#xff0c;双击pycharm的图标&#xff0c;打开pycharm。如果是首次使用的话选择Create New Project创建一个新项目。 进入pycharm后也可以通过以下方式新建一个项目&#xff0c;点击菜单栏File–New Project。 2. 选择项目路径和python环境&…

C++设计模式——抽象工厂模式

文章目录 抽象工厂模式的主要组成部分抽象工厂模式的一个典型例子抽象工厂模式用于其他场景抽象工厂模式与其他设计模式结合使用 C 中的抽象工厂模式是一种创建型设计模式&#xff0c;它主要用于处理对象家族的创建&#xff0c;这些对象之间可能存在一定的关联关系或属于相同的…

开仓济民 SWUST OJ 1175

有个王国在某年爆发了旱灾&#xff0c;于是那里的国王准备开仓济民。已知&#xff0c;第一天发一公斤粮食&#xff0c;第二天发两公斤粮食&#xff0c; 第三天发四公斤粮食。。。。。第二天发的粮食是前一天的两倍。我们已知安抚灾民一共需要m公斤粮食&#xff0c;问第几天国 王…