51nod 更难的矩阵取数问题 + 滚动数组优化
这里要求要走到终点再走回来,可以转化为两个人走。
那么我们可以先粗暴的设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;
}
51nod 更难的矩阵取数问题 + 滚动数组优化的更多相关文章
- 51nod 更难的矩阵取数问题(动态规划)
更难的矩阵取数问题 给定一个m行n列的矩阵,矩阵每个元素是一个正整数,你现在 在左上角(第一行第一列),你需要走到右下角(第m行,第n列),每次只能朝右或者下走到相邻的位置,不能走出矩阵.然后再从右下 ...
- [多路dp]更难的矩阵取数问题
https://www.51nod.com/tutorial/course.html#!courseId=11&isCurrent=1 解题关键:1.注意i和j的最大取值都是n,k是i与j的和 ...
- 51Nod 1083 矩阵取数问题(矩阵取数dp,基础题)
1083 矩阵取数问题 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题 一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下 ...
- 51Nod 1084 矩阵取数问题 V2 —— 最小费用最大流 or 多线程DP
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1084 1084 矩阵取数问题 V2 基准时间限制:2 秒 空 ...
- 51Nod 1084:矩阵取数问题 V2(多维DP)
1084 矩阵取数问题 V2 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 一个M*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励 ...
- 【NOIP2007】矩阵取数
因为傻逼写错高精度搞了一下午浪费好多时间,好想哭qaq 原题: 帅帅经常更同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij据为非负整数.游戏规则如下: 1. 每次取数时须从每 ...
- P1005 矩阵取数游戏 区间dp 高精度
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n \times mn×m的矩阵,矩阵中的每个元素a_{i,j}ai,j均为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n ...
- 1084 矩阵取数问题 V2
1084 矩阵取数问题 V2 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 一个M*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,先从左上走到右下 ...
- NOIP2007 矩阵取数游戏
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
随机推荐
- Thinking in States
Thinking in States Niclas Nilsson PEOPLE IN THE REAL WORLD HAVE A WEIRD RELATIONSHIP WITH STATE. Thi ...
- 【通信框架】Google的开源通信框架protobuf概述
在阅读的过程中有不论什么问题,欢迎一起交流 邮箱:1494713801@qq.com QQ:1494713801 一.作用 protobuf(Protocol Buffers)是Google内部 ...
- Java排序之直接选择排序
public class SelectSort { public static void selectSort(int [] a){ int min; int temp; if(a==null || ...
- 由老同事学习SAP所想到的
前段时间一位老同事在微信上跟我说他们公司正计划导SAP系统,但整个IT中心几乎无人使用过SAP,知道我在这行业干了多年了,所以想问我怎么开始学习.于是我约他今天出来聊聊,顺便把手里的SAP ECC E ...
- [JZOJ4272] [NOIP2015模拟10.28B组] 序章-弗兰德的秘密 解题报告(树形DP)
Description 背景介绍弗兰德,我不知道这个地方对我意味着什么.这里是一切开始的地方.3年前,还是个什么都没见过的少年,来到弗兰德的树下,走进了封闭的密室,扭动的封尘已久机关,在石板上知道了这 ...
- javascript中的那些宽度和高度
window.outerHeight和window.outerWidth 表示整个浏览器窗体的大小,包括任务栏等. IE9及以上 window.innerHeight和window.in ...
- Chromium Graphics: Multithreaded Rasterization
Multithreaded Rasterization @nduca, @enne, @vangelis (and many others) Implementation status: crbug. ...
- 【noip2016】蚯蚓(单调性+队列)
题目贼长 大意是你有n个线段,每一秒你要拿出来最长的一个线段切成两段长度为[p*u](向下取整)和u-[p*u]两段(其中u是线段长,p是一个大于0小于1的实数)没被切的线段长度加q(0<q&l ...
- [NOIP2014提高组]联合权值
题目:洛谷P1351.Vijos P1906.codevs3728.UOJ#16. 题目大意:有一个无向连通图,有n个点n-1条边,每个点有一个权值$W_i$,每条边长度为1.规定两个距离为2的点i和 ...
- 钓鱼WIFI的防范
实际上,Wi-Fi接入点(AP).路由器和热点常常是高度暴露的攻击面.用户一不小心就有可能踏进攻击者设置的Wi-Fi陷阱,为企业造成信息泄露或经济损失. 如今Wi-Fi 6时代悄然到来,为高密海量无线 ...