AcWing 1212. 地宫取宝 题解

2023-11-02 05:31
文章标签 acwing 题解 取宝 地宫 1212

本文主要是介绍AcWing 1212. 地宫取宝 题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目

在这里插入图片描述
在这里插入图片描述


思路

闫氏DP分析法:
在这里插入图片描述

状态表示

f [ i ] [ j ] [ k ] [ c ] f[i][j][k][c] f[i][j][k][c]

集合

所有从起点走到 ( i , j ) (i,j) (i,j),且已经取了 k k k件物品,且最后一件物品的价值为 c c c的方案数

因为“走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)
所以每一步,如果取,那它就必然是之前取过的所有数的最大值

属性

方案总数

状态计算

f [ i ] [ j ] [ k ] [ c ] f[i][j][k][c] f[i][j][k][c]的来源有四种:

  • 1:最后一步是从上往下走,且不取当前位置的宝物
    f [ i − 1 ] [ j ] [ k ] [ c ] f[i-1][j][k][c] f[i1][j][k][c]
  • 2:最后一步是从左往右走,且不取当前位置的宝物
    f [ i ] [ j − 1 ] [ k ] [ c ] f[i][j-1][k][c] f[i][j1][k][c]

第三种和第四种来源出现的必要条件:
当前k得大于0,因为当前是”取了的“,不可能为0否则就矛盾了
当前位置的宝物价值得等于c,因为取了的这个物品就是最后一件物品了

  • 3:最后一步是从上往下走,且取当前位置的宝物
    遍历所有上一步的可能的价值c,加到答案上就行

  • 4:最后一步是从左往右走,且取当前位置的宝物
    遍历所有上一步的可能的价值c,加到答案上就行

边界处理

f [ 1 ] [ 1 ] [ 1 ] [ w [ 1 ] [ 1 ] ] = 1 ; f[1][1][1][w[1][1]]=1; f[1][1][1][w[1][1]]=1;在起点处,如果取得话,最大物品的价值为起点处的宝物价值,这样的方案就只有一个
f [ 1 ] [ 1 ] [ 0 ] [ − 1 ] = 1 ; f[1][1][0][-1]=1; f[1][1][0][1]=1;在起点处,如果不取的话,取了0件,最大价值为-1,取-1是为了方便后面自然转移,但是我们又发现,数组下标没法有-1,怎么办,我们可以在读入地宫的时候,把所有宝物的价值+1,这样用0替代-1


代码

#include<iostream>
using namespace std;
const int N=55,MOD=1e9+7;
int f[N][N][15][14];
int w[N][N];
int n,m,k;
int main()
{scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++)   for(int j=1;j<=m;j++){scanf("%d",&w[i][j]);w[i][j]++;  //读入时,人为的全部+1,为了后面拿0替代-1}f[1][1][1][w[1][1]]=1;   //初始化边界f[1][1][0][0]=1;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)       //遍历整个地宫的所有点{if(i==1&&j==1) continue;   //因为初始化的时候做过了,不需要再考虑for(int u=0;u<=k;u++)       //遍历所有可能的方案数for(int v=0;v<=13;v++)     //遍历所有可能的最后取的(最大的)价值{int &val=f[i][j][u][v];val=(val+f[i-1][j][u][v])%MOD;val=(val+f[i][j-1][u][v])%MOD;if(u>0&&w[i][j]==v)    //如果当前考虑的方案数是比0大的,且当前价值就是当前位置的宝物价值,说明取了当前位置的宝物{for(int c=0;c<v;c++)  //遍历上一步所有可能的宝物价值取值{val=(val+f[i-1][j][u-1][c])%MOD;val=(val+f[i][j-1][u-1][c])%MOD;}}}}long long res=0;for(int i=0;i<=13;i++) res=(res+f[n][m][k][i])%MOD;  //算上所有终点的方案数为k的方案总数printf("%lld",res);                                  //主要是最后取得价值不同return 0;
}

这篇关于AcWing 1212. 地宫取宝 题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/328461

相关文章

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

【秋招笔试】9.07米哈游秋招改编题-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收集 100+ 套笔试题,笔试真题 会在第一时间跟新 🍄 题面描述等均已改编,如果和你笔试题看到的题面描述

LeetCode 第414场周赛个人题解

目录 Q1. 将日期转换为二进制表示 原题链接 思路分析 AC代码 Q2. 范围内整数的最大得分 原题链接 思路分析 AC代码 Q3. 到达数组末尾的最大得分 原题链接 思路分析 AC代码 Q4. 吃掉所有兵需要的最多移动次数 原题链接 思路分析 AC代码 Q1. 将日期转换为二进制表示 原题链接 Q1. 将日期转换为二进制表示 思路分析

【AcWing】851. 求最短路

spfa算法其实是对贝尔曼福特算法做一个优化。 贝尔曼福特算法会遍历所有边来更新,但是每一次迭代的话我不一定每条边都会更新,SPFA是对这个做优化。 如果说dist[b]在当前这次迭代想变小的话,那么一定是dist[a]变小了,只有a变小了,a的后继(b)才会变小。 用宽搜来做优化,用一个队列,队列里边存的就是所有变小了的结点(队列里存的是待更新的点)。 基本思路就是我更新过谁,我再拿

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

P2858 [USACO06FEB] Treats for the Cows G/S 题解

P2858 题意 给一个数组。每天把最左或者最右的东西卖掉,第 i i i个东西,第 d a y day day天卖出的价格是 a [ i ] ∗ d a y a[i]*day a[i]∗day。 记忆化搜索 void dfs(int l,int r,int day,ll sum){if(v[l][r]>=sum)return;v[l][r]=sum;if(l>r)//这就是dp答案{

【AcWing】852. spfa判断负环

#include<iostream>#include<algorithm>#include<cstring>#include<queue>using namespace std;const int N= 1e5+10;int n,m;int h[N],w[N],e[N],ne[N],idx;int dist[N],cnt[N];//cnt存最短路径的边数bool st[N];v

【C++题解】1272. 郭远摘苹果

欢迎关注本专栏《C++从零基础到信奥赛入门级(CSP-J)》 问题:1272. 郭远摘苹果 类型:二维数组 题目描述: 郭远有一天走到了一片苹果林,里面每颗树上都结有不同数目的苹果,郭远身上只能拿同一棵树上的苹果,他每到一棵果树前都会把自己身上的苹果扔掉并摘下他所在树上的苹果并带走(假设郭远会走过每一棵苹果树),问在郭远摘苹果的整个过程中,他身上携带的最多苹果数与最小苹果数的差是多少?