试题 算法提高 网格贪吃蛇(离散化 + DP)
创始人
2024-02-09 06:10:34

资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
  那个曾经风靡全球的贪吃蛇游戏又回来啦!这次贪吃蛇在m行n列的网格上沿格线爬行,从左下角坐标为(0,0)的格点出发,在每个格点处只能向上或者向右爬行,爬到右上角坐标为(m-1,n-1)的格点时结束游戏。网格上指定的格点处有贪吃蛇喜欢吃的豆豆,给定网格信息,请你计算贪吃蛇最多可以吃多少个豆豆。
输入格式
  输入数据的第一行为两个整数m、n(用空格隔开),分别代表网格的行数和列数;第二行为一个整数k,代表网格上豆豆的个数;第三行至第k+2行是k个豆豆的横纵坐标x、y(用空格隔开)。
输出格式
  程序输出一行,为贪吃蛇可吃豆豆的最大数量。
样例输入
10 10
10
3 0
1 5
4 0
2 5
3 4
6 5
8 6
2 6
6 7
3 1
样例输出
5
数据规模和约定

  1 ≤ m, n ≤ 106,0 ≤ x ≤ m-1,0 ≤ y ≤ n-1,1 ≤ k ≤ 1000
题目链接:网格贪吃蛇

分析:

  看完题,相信小伙伴很容易就会想到状态转移方程:因为dp[i][j]dp[i][j]dp[i][j]一定是dp[i−1][j]dp[i-1][j]dp[i−1][j]或者dp[i][j−1]dp[i][j-1]dp[i][j−1]转移过来的,但是一看数据规模,若开106 的二维 int 型数组(4 X 106 X 106 / 1024 / 1024 = 3814697MB),内存超限。
  再看 k 最大不超过 1000,将这 1000 个点离散化即可,开 103 的二维数组是不会内存超限的。
(PS:这是我第一次做离散化的题,看了相关知识点的视频,结合例子去理解到的,离散化的概念我就不赘述了,小伙伴可以先去搜索离散化的概念,再结合我的题解进行理解)。

思路:

  将所有点的横、纵坐标都存进同一个数组,然后从小到大排序,各个数字对应一个数组下标,将原来的点映射在新的以数组下标构成的坐标系,这就将其离散化了。下面结合例子以及图片进行理解。
假设有三个点(5,10),(41,16),(100,37),若以常规的100X100的坐标系,那么会有很多的空间浪费,
在这里插入图片描述

将其横纵坐标离散化,映射在新的坐标系:
在这里插入图片描述
那么原来的各个点在新坐标系的位置为:
  (5,10) -> (0,1), (41,16) -> (4,2), (100,37) -> (5,3)
这样就将 100X100 的空间减小到了 5X5,极大的节省了空间,这是解决本题的核心。
在这里插入图片描述

注意:在进行离散化时,需要对数字进行去重,避免出现以下的情况,不然映射新的坐标系会产生歧义,导致错误:
在这里插入图片描述

代码(细节写在了注释):

import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;public class Main {static int m, n, k;static dot[] dots = new dot[1005];	//存放点的数组//长度为2000是因为横纵坐标都要映射为数组下标,共2000static int[][] g = new int[2010][2010];	//新的坐标系static int[][] dp = new int[2010][2010];public static void main(String[] args) {Scanner sc = new Scanner(System.in);m = sc.nextInt(); n = sc.nextInt(); k = sc.nextInt();//存横纵坐标的数字的集合,采用HashSet自动去重Set nums = new HashSet<>();for (int i = 1; i <= k; i++) {int x = sc.nextInt();int y = sc.nextInt();dots[i] = new dot(x, y);	//将点放入点数组nums.add(x);	//将x,y加入集合nums.add(y);}Integer[] arrNums = nums.toArray(new Integer[nums.size()]);	//set转为数组Arrays.sort(arrNums);	// 排序/离散化,每个数字对应一个数组下标for (int i = 1; i <= k; i++) {	//将原来各坐标映射到新坐标系int x = find(dots[i].x, arrNums);//找到映射的点(x,y)int y = find(dots[i].y, arrNums);//这里的x,y都是从0开始,我习惯从1开始,就加了1,也方便后面dp的运算g[x+1][y+1] = 1;	}int len = arrNums.length;for (int i = 1; i <= len; i++) {for (int j = 1; j <= len; j++) {dp[i][j] = g[i][j];dp[i][j] += Math.max(dp[i-1][j],dp[i][j-1]);}}System.out.println(dp[len][len]);}public static int find(int x, Integer[] arr) {//二分查找映射的下标int l = 0, r = arr.length - 1;while(l < r) {int mid = (l + r) >> 1;if(x == arr[mid])return mid;if(x < arr[mid])r = mid;else l = mid + 1;}return l;}
}
class dot{int x, y;public dot(int x, int y) {this.x = x;this.y = y;}
}

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...