news 2026/6/14 21:34:26

方格取数 矩阵取数游戏 -动态规划

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
方格取数 矩阵取数游戏 -动态规划

方格取数

这道题我首先想到用二维数组,二维的思路偏向贪心算法,即定义dp[ i ][ j ]为走到点[ i , j ]时的最佳选项,此时保证第一遍走的时候为最佳答案,第二遍走时为去掉第一遍走过的点时的最佳答案,保证两遍都是分别的最佳答案但非整体的最佳答案……也就是说由于第一遍是只走当前最优的,容易导致第二遍走时取不到更好的值(有只能向下或向右走的限制)。然后会发现我们无法全部走完,也正符合贪心策略,“只注重眼前的利益”,因此此题使用二维dp绝非正解。代码如下。

二维dp

#include<bits/stdc++.h> using namespace std; const int N=11; int dp1[N][N],dp2[N][N],n,o; struct point { int x; int y; int num; }poi[N*N]; void find(int k,int l)//判断第一遍走过哪些点 { if(k==0&&l==0) { return; } else { if(dp1[k][l]-dp2[k][l]==dp1[k-1][l]) { dp2[k][l]=0; find(k-1,l); } else if(dp1[k][l]-dp2[k][l]==dp1[k][l-1]) { dp2[k][l]=0; find(k,l-1); } } } int main() { scanf("%d",&n); for(;;) { o++; scanf("%d%d%d",&poi[o].x,&poi[o].y,&poi[o].num); if(poi[o].x==poi[o].y&&poi[o].y==poi[o].num&&poi[o].num==0) { break; } else { dp1[poi[o].x][poi[o].y]=poi[o].num; dp2[poi[o].x][poi[o].y]=poi[o].num; } } for(int i=1;i<=n;i++)//第一遍的最优解 { for(int j=1;j<=n;j++) { dp1[i][j]+=max(dp1[i-1][j],dp1[i][j-1]); } } find(n,n); for(int i=1;i<=n;i++)//第二遍的最优解 { for(int j=1;j<=n;j++) { dp2[i][j]+=max(dp2[i-1][j],dp2[i][j-1]); } } printf("%d",dp1[n][n]+dp2[n][n]);//输出答案 return 0; }

因此我搜题解学习了动态规划的dp,这道题应该应用4维dp。

  1. 状态:定义一个四维数组 f,f[i][j][k][l]表示第一次走到第 i 行,第 j 列,第二次到达第 k 行,第 l 列能获得的最大值。

  2. 状态转移方程:我们要考虑以下四种情况:

  • 第一次从左边过来,第二次从左边过来

  • 第一次从左边过来,第二次从上边过来

  • 第一次从上边过来,第二次从左边过来

  • 第一次从上边过来,第二次从上边过来

那么我们就要取这四种情况的最大值了,即:f[i][j][k][l] = max(max(f[i-1][j][k-1][l],f[i-1][j][k][l-1]),max(f[i][j-1][k-1][l],f[i][j-1][k][l-1])) + a[i][j] + a[k][l]。

但要注意的是,如果 (i,j)=(k,l),那么就只能加其中一个(不能重复),所以此时要在原来的基础上减去一个a[i][j]。

3.初始化:刚开始也就是到点 (1,1) 能获得的最大值,即f[1][1][1][1]​=0。

4.答案:由于我们要求第一次和第二次走到右下角的最大值,所以我们的答案为 f[n][n][n][n]​。

四维dp

#include<bits/stdc++.h> using namespace std; int n,x,y,z,a[12][12] = {0},f[12][12][12][12];//表示第一次走到第i行,第j列,第二次到达第k行,第l列能获得的最大值。 int main() { cin >> n; cin >> x >> y >> z ; while(x!=0||y!=0||z!=0) { a[x][y] = z; cin >> x >> y >> z ; } for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { for(int k=1; k<=n; k++) { for(int l=1; l<=n; l++) { f[i][j][k][l] = max(max(f[i-1][j][k-1][l],f[i-1][j][k][l-1]),max(f[i][j-1][k-1][l],f[i][j-1][k][l-1])) + a[i][j] + a[k][l]; if(i == k && j == l) f[i][j][k][l] -= a[i][j];//如果位置相同,则减去其中一个 } } } } cout << f[n][n][n][n] << endl; return 0; }

矩阵取数游戏

/

求n行最大得分和,每一行取数又不会影响到其他行,那么只要确保每一行得分最大,管好自家孩子就行了。(这个在动规中叫最优子结构

每次取数是在边缘取,那么每次取数完剩下来的元素一定是在一个完整的一个区间中,又是求最优解,区间DP应运而生。

首先明确每行怎么取是没关联的,所以可以看成 n 行每行跑一次区间 dp。对于每行,设 fl,r​ 表示取区间 l 到 r 的最大值,这明显从大区间向小区间转移,但这里说一下从小区间向大区间转移。

对于一个区间,它乘的 2i 的这个 i 是第 i 次取数,就应等于区间长度,一个长度为 len 的区间从 len−1 转移得到,所以每次转移乘 2 就可以解决答案乘 2i 的问题。这里要好好体会。

记 ai​ 表示这一行的第 i 个数,对于区间 l 到 r,可以先取 al​,可以先取 ar​,转移是 fl,r​=max(fl+1,r​+al​,fl,r−1​+ar​)×2。

答案就是 n 次 f1,m​ 之和。

#include <bits/stdc++.h> using namespace std; int n, m, a[90][90]; __int128 f[90][90], ans; void out (__int128 x) { if(x>9) out(x/10); putchar(x%10+'0'); } int main () { cin >> n >> m; for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) cin >> a[i][j]; for (int i=1; i<=n; ans+=f[1][m], memset(f, 0, sizeof f), ++i) for (int len=1; len<=m; ++len) for (int l=1, r=l+len-1; r<=m; ++l, ++r) f[l][r]=max(f[l+1][r]+a[i][l], f[l][r-1]+a[i][r])*2; out(ans); return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 13:47:11

暗黑2重制版智能助手Botty:新手必学的自动化刷怪技巧

还在为重复刷怪感到枯燥乏味吗&#xff1f;&#x1f914; 暗黑2重制版自动化神器Botty横空出世&#xff0c;让你彻底解放双手&#xff0c;享受轻松游戏时光&#xff01;这款基于图像识别技术的智能工具&#xff0c;能够模拟真实玩家操作&#xff0c;实现高效自动化刷怪流程。 【…

作者头像 李华
网站建设 2026/6/15 14:11:04

IDM使用技术全解析:从入门到精通的完整指南

还在为Internet Download Manager的试用期限制而困扰吗&#xff1f;今天&#xff0c;我们将深入探讨一套成熟稳定的IDM使用技术方案&#xff0c;助你彻底摆脱试用期烦恼。 【免费下载链接】IDM-Activation-Script IDM Activation & Trail Reset Script 项目地址: https:/…

作者头像 李华
网站建设 2026/6/15 12:15:05

GB/T 7714参考文献格式全攻略:从格式困扰到高效写作

GB/T 7714参考文献格式全攻略&#xff1a;从格式困扰到高效写作 【免费下载链接】Chinese-STD-GB-T-7714-related-csl GB/T 7714相关的csl以及Zotero使用技巧及教程。 项目地址: https://gitcode.com/gh_mirrors/chi/Chinese-STD-GB-T-7714-related-csl 还在为论文参考文…

作者头像 李华
网站建设 2026/6/15 11:20:18

告别App Store限制:ipatool如何用5行命令解锁iOS应用自由

告别App Store限制&#xff1a;ipatool如何用5行命令解锁iOS应用自由 【免费下载链接】ipatool Command-line tool that allows searching and downloading app packages (known as ipa files) from the iOS App Store 项目地址: https://gitcode.com/GitHub_Trending/ip/ipa…

作者头像 李华
网站建设 2026/6/15 12:17:46

基于HAL库的CubeMX ADC单通道采样全面讲解

从零开始搞懂STM32 ADC单通道采样&#xff1a;CubeMX HAL实战全解析 你有没有遇到过这种情况&#xff1f;接了一个温度传感器&#xff0c;代码写完一烧录&#xff0c;串口打印出来的数值跳得像心电图&#xff1b;或者明明输入是1.65V&#xff0c;读出来却是2000多——离4095差…

作者头像 李华
网站建设 2026/6/15 11:19:47

戴森电池开源固件深度探索:5大隐藏功能完整揭秘

为什么你的戴森吸尘器会在两年后突然"死亡"&#xff1f;这并非偶然故障&#xff0c;而是原厂精心设计的"计划性报废"策略。通过开源固件&#xff0c;我们不仅能够解锁被隐藏的电池平衡功能&#xff0c;更能彻底改变产品的使用体验。 【免费下载链接】FU-Dy…

作者头像 李华