AcWing 1212. 地宫取宝 java 动态规划

👨‍🏫 集合划分依据:找最后一个不同点

👨‍🏫 边界问题(出口 ):从实际问题出发

① 用到 i-1 ,j-1 ,下标从 1 开发,减少特判

🐷 地宫取宝

🧐 解题思路

① 两维存坐标 下 x y,一维存 最大值(不是最大值的所在坐标),再一维存当前已取个数
② 复杂度预估:x: 50,y:50,最大值:12,取得个数:13;
   50*50*12*13 ≈4 * 10^5   ->  10^7 / 4*10^5 = 25 
③ 四重for循环 + 状态计算 (刚刚好hh)
④ 集合划分:
 ⭐ 一分 从左往右走 和 从上往下走 
 ⭐ 二分 取当前点 和 不取当前点
  ✨ 对于 取 的情况 
  ✨ 三分 取当前数 之前的 最大值是什么
⑤ 结果: f [n][m][k][i], 1 <= i <= 13;

👨‍🏫 因为物品的值有可能是 0 ,所以 得用到 -1 初始化没取一个宝的情况,但是数组下标不能为 负数   ,
     所以直接给所有价值+10 表示一件未取的情况
👨‍🏫 运算记得按题目要求取模,防止溢出 

在这里插入图片描述

import java.util.*;

public class Main
{
	static int N = 55, M = 15, MOD = (int) 1e9 + 7;
	static int n, m, c;
	static int[][] a = new int[N][N];
	//状态数组,相当于坑位,从前往后枚举,找到符合条件的方案就填进坑位里边 存的值是当前状态的方案数
	static int[][][][] f = new int[N][N][M][M];

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		c = sc.nextInt();

		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
			{
				a[i][j] = sc.nextInt();
				a[i][j]++;
			}

//		初始化边界
		f[1][1][0][0] = 1;// 不选的情况,最大值 为 -1 + 1 = 0
		f[1][1][1][a[1][1]] = 1;// 选 1

		for (int i = 1; i <= n; i++)// i 是横坐标
			for (int j = 1; j <= m; j++)// j 是纵坐标
				for (int cnt = 0; cnt <= c; cnt++)// cnt 是已取数 个数
					for (int max = 0; max < M; max++)// k 是 已取数中的最大的值
					{
//						不取
//                      没有加入新的宝,对于数量和最大值都是没有影响的
						f[i][j][cnt][max] = (f[i][j][cnt][max] + f[i - 1][j][cnt][max]) % MOD;// 不使用 += 是为了方便取模
						f[i][j][cnt][max] = (f[i][j][cnt][max] + f[i][j - 1][cnt][max]) % MOD;  

//                      cnt > 0 表示前边有数了
						if (cnt > 0 && max == a[i][j])// k == a[i][j] ,条件符合,可以填坑
						{
						    // 可以拿的情况
//							枚举前边的方案(前一个最大值)
							for (int s = 0; s < max; s++)
							{
    //                          s 是已取数 倒数第二位的 值 
								f[i][j][cnt][max] = (f[i][j][cnt][max] + f[i - 1][j][cnt - 1][s]) % MOD;
								f[i][j][cnt][max] = (f[i][j][cnt][max] + f[i][j - 1][cnt - 1][s]) % MOD;
							}
						}
					}
		long res = 0;
		for (int i = 0; i < M; i++)
			res = (res + f[n][m][c][i]) % MOD;

		System.out.println(res);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
鉴于提供的内容是一段包含三个不同的Java程序的代码,我无法提供一个完整的答案来回答你的问题。但是,我可以为你提供一些信息。 根据引用和引用的内容,这两个程序都涉及到动态规划算法。引用中的程序解决了一个关于序列的最长递增子序列的问题,而引用中的程序解决了一个关于背包问题的二维动态规划的问题。 对于引用中的内容,它是一个程序解决的是一个最长上升子序列的问题。 根据提供的代码,这些程序可能是用来解决一些蓝桥杯竞赛的题目。然而,我无法提供更多关于具体问题的信息。 如果你需要帮助解决特定的问题,我建议你仔细阅读每个程序的代码并理解它们的功能,然后根据需要进行相应的修改。如果你有关于动态规划或蓝桥杯竞赛的更具体的问题,我会很愿意帮助你。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [蓝桥杯AcWing学习笔记 3-2简单DP的学习(附相关蓝桥真题:地宫取宝、波动数列)(Java)](https://blog.csdn.net/weixin_53407527/article/details/123122245)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值