基准时间限制:2 秒 空间限制:131072 KB 
一个M*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,先从左上走到右下,再从右下走到左上。第1遍时只能向下和向右走,第2遍时只能向上和向左走。两次如果经过同一个格子,则该格子的奖励只计算一次,求能够获得的最大价值。

 
例如:3 * 3的方格。
 
1 3 3
2 1 3
2 2 1
 
能够获得的最大价值为:17。1 -> 3 -> 3 -> 3 -> 1 -> 2 -> 2 -> 2 -> 1。其中起点和终点的奖励只计算1次。
 
Input
第1行:2个数M N,中间用空格分隔,为矩阵的大小。(2 <= M, N <= 200)
第2 - N + 1行:每行M个数,中间用空格隔开,对应格子中奖励的价值。(1 <= A[i,j] <= 10000)
Output
输出能够获得的最大价值。
Input示例
3 3
1 3 3
2 1 3
2 2 1
Output示例
17

思路:双线DP,看成两个人一起从(1,1)到(N,M),走的路径不能相同。

方法1:按照路径长度考虑,路径总长度:tot=x+y-1,dp[tot][x1][x2],两个人的横坐标x1,x2

 #include <bits/stdc++.h>
using namespace std;
int ans[][],dp[][][];
int main() {
int M,N;
scanf("%d %d",&M,&N);
for(int i=;i<=N;++i)
for(int j=;j<=M;++j)
scanf("%d",&ans[i][j]);
memset(dp,,sizeof(dp));
for(int tot=;tot<=N+M-;++tot)//路径长度
for(int i=;i<=N&&(<=tot+-i);++i)
for(int j=;j<=N&&(<=tot+-j);++j) {
dp[tot][i][j]=max(dp[tot][i][j],dp[tot-][i-][j-]);
dp[tot][i][j]=max(dp[tot][i][j],dp[tot-][i-][j]);
dp[tot][i][j]=max(dp[tot][i][j],dp[tot-][i][j-]);
dp[tot][i][j]=max(dp[tot][i][j],dp[tot-][i][j])+ans[i][tot+-i]+ans[j][tot+-j];
if(i==j) dp[tot][i][j]-=ans[i][tot+-i];
}
printf("%d\n",dp[N+M-][N][N]);
return ;
}

方法2:按照走到走了几步,总的步数:tot=x+y-2

 #include <bits/stdc++.h>
using namespace std;
int ans[][],dp[][][];
int main() {
int M,N;
scanf("%d %d",&M,&N);
for(int i=;i<=N;++i)
for(int j=;j<=M;++j)
scanf("%d",&ans[i][j]);
memset(dp,,sizeof(dp));
dp[][][]=ans[][];//一步都没走
for(int tot=;tot<=N+M-;++tot)//走了几步
for(int i=;i<=N&&(i-<=tot);++i)
for(int j=;j<=N&&(j-<=tot);++j) {
dp[tot][i][j]=max(dp[tot][i][j],dp[tot-][i-][j-]);
dp[tot][i][j]=max(dp[tot][i][j],dp[tot-][i-][j]);
dp[tot][i][j]=max(dp[tot][i][j],dp[tot-][i][j-]);
dp[tot][i][j]=max(dp[tot][i][j],dp[tot-][i][j])+ans[i][tot+-i]+ans[j][tot+-j];
if(i==j) dp[tot][i][j]-=ans[i][tot+-i];
}
printf("%d\n",dp[N+M-][N][N]);
return ;
}

方法3:对方法2的优化,滚动数组

 #include <stdio.h>
#include <string.h>
int ans[][],dp[][][];
int max(int a, int b) {if(a>=b) return a;return b;}
int main() {
int M,N;
scanf("%d %d",&M,&N);
for(int i=;i<=N;++i)
for(int j=;j<=M;++j)
scanf("%d",&ans[i][j]);
memset(dp,,sizeof(dp));
dp[][][]=ans[][];//一步都没走
int dir=;
//tot->走了几步
for(int tot=;tot<=N+M-;++tot) {
dir=-dir;
for(int i=;i<=N&&(i-<=tot);++i)
for(int j=;j<=N&&(j-<=tot);++j) {
dp[dir][i][j]=max(dp[dir][i][j],dp[-dir][i-][j-]);
dp[dir][i][j]=max(dp[dir][i][j],dp[-dir][i-][j]);
dp[dir][i][j]=max(dp[dir][i][j],dp[-dir][i][j-]);
dp[dir][i][j]=max(dp[dir][i][j],dp[-dir][i][j])+ans[i][tot+-i]+ans[j][tot+-j];
if(i==j) dp[dir][i][j]-=ans[i][tot+-i];
}
}
printf("%d\n",dp[dir][N][N]);
return ;
}

51Nod 1084 矩阵取数问题 V2 双线程DP 滚动数组优化的更多相关文章

  1. 51Nod 1084 矩阵取数问题 V2 —— 最小费用最大流 or 多线程DP

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1084 1084 矩阵取数问题 V2  基准时间限制:2 秒 空 ...

  2. 1084 矩阵取数问题 V2

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

  3. 51Nod 1084:矩阵取数问题 V2(多维DP)

    1084 矩阵取数问题 V2  基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 一个M*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励 ...

  4. 51nod1084 矩阵取数问题 V2

    O(n4)->O(n3)妈呀为什么跑这么慢woc #include<cstdio> #include<cstring> #include<cctype> #i ...

  5. 51Nod 1083 矩阵取数问题(矩阵取数dp,基础题)

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

  6. [Swust OJ 1084]--Mzx0821月赛系列之情书(双线程dp)

    题目链接:http://acm.swust.edu.cn/problem/1084/ Time limit(ms): 1000 Memory limit(kb): 65535   Descriptio ...

  7. 51nod 1411 矩阵取数问题 V3

    给定一个m行n列的矩阵,你可以从任意位置开始取数,到达任意位置都可以结束,每次可以走到的数是当前这个数上下左右的邻居之一,唯一的限制是每个位置只能经过一次,也就是说你的路径不自交.所经过的数的总作为你 ...

  8. 51nod动态规划-----矩阵取数

    一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下向右走,求能够获得的最大价值. 例如:3 * 3的方格. 1 3 3 2 1 3 2 2 1 能够获得的最 ...

  9. 51nod 1083 矩阵取数问题【动态规划】

    一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下向右走,求能够获得的最大价值. 例如:3 * 3的方格. 1 3 3 2 1 3 2 2 1 能够获得的最 ...

随机推荐

  1. [LeetCode] Reverse Pairs 翻转对

    Reverse Pairs 翻转对 题意 计算数组里面下标i小于j,但是i的值要大于j的值的两倍的搭配的个数(也就是可能会有多种搭配):网址 做法 这道题显然是不允许使用最简单的方法:两次循环,逐次进 ...

  2. Linux学习(三)putty,xshell使用以及密匙登陆

    一.认识xshell,putty 他们都是服务器登陆客户端.xshell用户体验更好一点.但这里都学一下. putty下载地址:https://www.chiark.greenend.org.uk/~ ...

  3. HDU1792A New Change Problem(GCD规律推导)

    A New Change Problem Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  4. 0_Simple__cdpSimplePrint + 0_Simple__cdpSimpleQuicksort

    CUDA动态并行的简单实践,以及利用CUDA动态并行实现快排算法(有单线程的递归调用) ▶ 源代码:动态并行递归调用线程块 #include <iostream> #include < ...

  5. C# group 子句

    group 子句返回一个 IGrouping<TKey,TElement> 对象序列,这些对象包含零个或更多与该组的键值匹配的项. 例如,可以按照每个字符串中的第一个字母对字符串序列进行分 ...

  6. AngularJS学习篇(十五)

    AngularJS 模块 模块定义了一个应用程序. 模块是应用程序中不同部分的容器. 模块是应用控制器的容器. 控制器通常属于一个模块. 创建模块 你可以通过 AngularJS 的 angular. ...

  7. CentOS7配置更新国内yum源

    备份本地yum源文件 cd /etc/yum.repo.d/ mv CentOS-Base.repo CentOS-Base.repo.bakeup 下载国内yum源 阿里云yum源 wget htt ...

  8. ④bootstrap列表使用基础案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. java 中 final 的用法

    /* final可以修饰类,方法,变量 特点: final可以修饰类,该类不能被继承. final可以修饰方法,该方法不能被重写.(覆盖,复写) final可以修饰变量,该变量不能被重新赋值.因为这个 ...

  10. 问题:编译eshoponcontainers失败,提示error:invalid reference format

    环境: visual studio 2017 v15.4.2,docker ce Version 17.06.0-ce-win19 (12801) 参考问题页: https://github.com/ ...