这里要求要走到终点再走回来,可以转化为两个人走。

那么我们可以先粗暴的设f[x1][y1][x2][y2]为第一个人走到(x1, y1), 第二个人走到(x2, y2)的最大价值。

那么这样空间会很大,通过观察可以发现,一个走的步数=横坐标+纵坐标,因为走一步一定是横坐标

或者纵坐标+1.

那么我们就可以转化为f[step][x1][x2],可以退出y1 = step - x1, y2 = step - x2

那么转移方程就很好求了

f[step][x1][x2] = max(f[step-1][x1-1][x2], f[step-1][x1-1][x2-1], f[step-1][x1][x2-1], f[step-1][x1][x2]) + a[i][step-i]

+ (i == j ? 0 : a[j][step-j])

这里要判断如果是同一个格子的话只加一次。

实际这样已经可以过了,代码如下

#include<cstdio>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;const int MAXN = 212;
int f[MAXN*2][MAXN][MAXN];
int a[MAXN][MAXN], n, m;void up(int& x, int a) { x = max(x, a); }int main()
{scanf("%d%d", &m, &n);REP(i, 1, n + 1)REP(j, 1, m + 1)scanf("%d", &a[i][j]);REP(k, 2, n + m + 1){for(int i = 1; i <= n && i + 1 <= k; i++)for(int j = 1; j <= n && j + 1 <= k; j++){for(int r1 = -1; r1 <= 0; r1++)for(int r2 = -1; r2 <= 0; r2++)up(f[k][i][j], f[k - 1][i + r1][j + r2]);f[k][i][j] += a[i][k-i] + (i == j ? 0 : a[j][k-j]);}}printf("%d\n", f[n + m][n][n]);return 0;
} 

但是呢其实空间上还可以更优化,因为只和k-1有关

那么我这里想到两种方法实现滚动数组。

第一个就是开两个二维数组,然后就来回更新。

#include<cstdio>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;const int MAXN = 212;
int f[2][MAXN][MAXN];
int a[MAXN][MAXN], n, m;void up(int& x, int a) { x = max(x, a); }int main()
{scanf("%d%d", &m, &n);REP(i, 1, n + 1)REP(j, 1, m + 1)scanf("%d", &a[i][j]);int t = 0;REP(k, 2, n + m + 1){for(int i = 1; i <= n && i + 1 <= k; i++)for(int j = 1; j <= n && j + 1 <= k; j++){for(int r1 = -1; r1 <= 0; r1++)for(int r2 = -1; r2 <= 0; r2++)up(f[t][i][j], f[t ^ 1][i + r1][j + r2]);f[t][i][j] += a[i][k-i] + (i == j ? 0 : a[j][k-j]);}t ^= 1;    }printf("%d\n", f[t ^ 1][n][n]);return 0;
} 

还一种有点类似01背包逆推那个做法,只用一个数组就可以实现,改变循环顺序就好了。

为了让当前状态转移的时候,用来更新的值都是上一行的,所以我们要逆序来操作。

因为如果是从上到下,从左到右的话,要更新当前状态,需要用到f[i-1][j]等,而这个时候

f[i-1][j]之前已经算过了,已经更新过了,只要更新过了就成了这一行的值了,就不行。

所以我们要让f[i-1][j], f[i-1][j-1], f[i][j-1],f[i][j]都没有更新过。

所以我们就从下到上,从右到左来推,这样就可以保证都是上一行的值了。

#include<cstdio>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;const int MAXN = 212;
int f[MAXN][MAXN];
int a[MAXN][MAXN], n, m;void up(int& x, int a) { x = max(x, a); }int main()
{scanf("%d%d", &m, &n);REP(i, 1, n + 1)REP(j, 1, m + 1)scanf("%d", &a[i][j]);REP(k, 2, n + m + 1){for(int i = min(n, k - 1); i >= 1; i--)for(int j = min(n, k - 1); j >= 1; j--){for(int r1 = -1; r1 <= 0; r1++)for(int r2 = -1; r2 <= 0; r2++)up(f[i][j], f[i + r1][j + r2]);f[i][j] += a[i][k-i] + (i == j ? 0 : a[j][k-j]);}}printf("%d\n", f[n][n]);return 0;
} 

转载于:https://www.cnblogs.com/sugewud/p/9819437.html

51nod 更难的矩阵取数问题 + 滚动数组优化相关推荐

  1. 【区间DP+高精】codevs1166 矩阵取数游戏题解

    转自: [ametake版权所有]http://blog.csdn.net/ametake欢迎来看 http://blog.csdn.net/ametake/article/details/47664 ...

  2. 【日常学习】【区间DP+高精】codevs1166 矩阵取数游戏题解

    题目来自NOIP2007TG3 如果在考场上我现在已经歇菜了吧 今天一整天的时间全部投在这道题上,收获不小. 先上题目 题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏 ...

  3. TYVJ 矩阵取数 Label:高精度+dp

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  4. 【每日DP】day 10、P1005 矩阵取数游戏【区间DP+高精(python)】难度⭐⭐⭐★

    P1005 矩阵取数游戏 输入 2 3 1 2 3 3 4 2 输出 82 说明/提示 NOIP 2007 提高第三题. 数据范围: 60%60\%60% 的数据满足:1≤n,m≤301\le n,m ...

  5. P1005 矩阵取数游戏(__int128模板/简单dp)

    转跳P1005 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的 n \times mn×m 的矩阵,矩阵中的每个元素 a_{i,j}a i,j ​ 均为非负整数.游戏规则如下: 每次取数时 ...

  6. 【每日一题】7月10日精讲—矩阵取数游戏

    来源:牛客网: 文章目录 题目描述 题解: 代码: 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld ...

  7. [JZOJ P1288] [DP]矩阵取数

    @kaike 传送门 07年noipT3? 要我写我肯定放弃 嗯没错就是这么果断 据说要 高精 DP 状态? 举例说明,假设有矩阵 a1,a2,a3,a4....an b1,b2,b3,b4....b ...

  8. 洛谷1005 【NOIP2007】矩阵取数游戏

    问题描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  9. 【codevs1166】【noip07TG】矩阵取数游戏,新的开始

    1166 矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description [问题描述] 帅帅经 ...

  10. 51Nod-1083 矩阵取数问题【DP】

    1083 矩阵取数问题 基准时间限制:1秒 空间限制:131072KB 分值:5难度:1级算法题 一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下向右走, ...

最新文章

  1. 洛谷P1525 关押罪犯
  2. nginx 1.9.9 Linux 环境安装
  3. kali linux 模板文件夹,详解kali linux 常用文件与指令路径
  4. ue4缓存位置怎么改_[UE4]动态液体材质浅谈
  5. Java基础知识总结(超详细整理),java从入门到精通pdf
  6. 计算机考研复试之计算机网络
  7. 搭建 Harbor v2.2.0 docker私库
  8. 配置p6spy打印完整sql语句
  9. empty怎么发音_英语单词empty怎么读,empty的音标是什么,empty是什么意思 - 音标网...
  10. BZOJ 3162:独钓寒江雪
  11. 自然语言三兄弟NLP、NLU、NLG傻傻分不清?一文搞懂它们的区别
  12. android 日语输入法,Android日语输入法Simeji使用示例
  13. sml基本语法(三)——函数
  14. Microsoft Exchange Server 2007: Tony Redmond's Guide to Successful Implementation
  15. 专访IBM孙震:流程挖掘行业前景广阔,市场教育待完成
  16. 开源多端合一小程序源码系统+前端+后端+搭建教程
  17. 怎么禁止windows音频设备图形隔离程序_Windows 10中音频设备图形间隔内存占用较高的处理方法...
  18. 什么软件可以搜索python答案_module是什么意思_module的翻译_音标_读音_用法_例句_爱词霸在线词典...
  19. 一篇理解GFS与HDFS的重要理念
  20. 培训有毛用!大会有毛用!

热门文章

  1. 第二阶段冲刺10天 第二天
  2. Oracle Temp表空间切换
  3. Maven如何手动添加jar包到本地Maven仓库
  4. 筛选DataTable数据的方法
  5. 关于js中的this关键字
  6. bzoj4695 最假女选手(势能线段树/吉司机线段树)题解
  7. Java开发之@PostConstruct和@PreDestroy注解
  8. windows service 2008 R2 安装net4.6环境失败,windows service 2008 R2 升级sp1问题
  9. BZOJ_1626_[Usaco2007_Dec]_Building_Roads_修建道路_(Kruskal)
  10. 【转帖】Mysql多维数据仓库指南 第一篇 第1章