CH5103 传纸条【线性dp】

5103 传纸条 0x50「动态规划」例题

描述

给定一个 N*M 的矩阵A,每个格子中有一个整数。现在需要找到两条从左上角 (1,1) 到右下角 (N,M) 的路径,路径上的每一步只能向右或向下走。路径经过的格子中的数会被取走。两条路径不能经过同一个格子。求取得的数之和最大是多少。N,M≤50。

输入格式

第一行有2个用空格隔开的整数n和m,表示有n行m列(1<=n,m<=50)。
接下来的n行是一个n*m的矩阵,每行的n个整数之间用空格隔开。

输出格式

一个整数,表示答案。

样例输入

3 3
0 3 9
2 8 5
5 7 0

样例输出

34

数据范围与约定

  • 30%的数据满足:1<=m,n<=10 
    100%的数据满足:1<=m,n<=50

来源

CCF NOIP2008 T3

题意:n*m的格子里每个格子有一个权值,从(1,1)走到(n,m)两条路,(只能向下或者向右)求路径之和。走过的格子只算一次权值。

思路:

把“路径长度”即当前走过的步数作为DP的“阶段”。【因为只能向下或向右,走到(n,m)时的路径长度是n+m-2】

每一个阶段中,把两条路径同时扩展一步,路径长度增加1,从而转移到下一个阶段。

还需确定两条路径当前的末尾位置。并且 x1+y1 = x2 + y2 = i + 2

所以就可以用三维dp维护,每次有4种扩展方式。并且要考虑扩展后是否两个点坐标相同。

目标是dp[n+m-2][n][n]

 1 #include <bits/stdc++.h>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stdio.h>
 6 #include<cstring>
 7 #include<map>
 8
 9 #define inf 0x3f3f3f3f
10 using namespace std;
11 typedef long long LL;
12
13 int n, m;
14 const int maxn = 55;
15 int g[maxn][maxn];
16 int dp[maxn * 2][maxn][maxn] = {0};
17
18 int main()
19 {
20     scanf("%d%d", &n, &m);
21     for(int i = 1; i <= n; i++){
22         for(int j = 1; j <= m; j++){
23             scanf("%d", &g[i][j]);
24         }
25     }
26
27     dp[0][1][1] = g[1][1];
28     for(int i = 0; i <= n + m - 2; i++){
29         for(int x1 = 1; x1 <= min(n, i + 1); x1++){
30             for(int x2 = 1; x2 <= min(n, i + 1); x2++){
31                 int y1 = i + 2 - x1, y2 = i + 2 - x2;
32                 if(x1 == x2 && y1 == y2){
33                     dp[i + 1][x1][x2] = max(dp[i + 1][x1][x2], dp[i][x1][x2] + g[x1][y1 + 1]);
34                     dp[i + 1][x1 + 1][x2 + 1] = max(dp[i + 1][x1 + 1][x2 + 1], dp[i][x1][x2] + g[x1 + 1][y1]);
35                 }
36                 else{
37                     dp[i + 1][x1][x2] = max(dp[i + 1][x1][x2], dp[i][x1][x2] + g[x1][y1 + 1] + g[x2][y2 + 1]);
38                     dp[i + 1][x1 + 1][x2 + 1] = max(dp[i + 1][x1 + 1][x2 + 1], dp[i][x1][x2] + g[x1 + 1][y1] + g[x2 + 1][y2]);
39                 }
40
41                 if(x1 == x2 + 1 && y1 + 1 == y2){
42                     dp[i + 1][x1][x2 + 1] = max(dp[i + 1][x1][x2 + 1], dp[i][x1][x2] + g[x1][y1 + 1]);
43                 }
44                 else{
45                     dp[i + 1][x1][x2 + 1] = max(dp[i + 1][x1][x2 + 1], dp[i][x1][x2] + g[x1][y1 + 1] + g[x2 + 1][y2]);
46                 }
47
48                 if(x1 + 1 == x2 && y1 == y2 + 1){
49                     dp[i + 1][x1 + 1][x2] = max(dp[i + 1][x1 + 1][x2], dp[i][x1][x2] + g[x1 + 1][y1]);
50                 }
51                 else{
52                     dp[i + 1][x1 + 1][x2] = max(dp[i + 1][x1 + 1][x2], dp[i][x1][x2] + g[x1 + 1][y1] + g[x2][y2 + 1]);
53                 }
54             }
55         }
56     }
57     printf("%d\n", dp[n + m - 2][n][n]);
58     return 0;
59 }

原文地址:https://www.cnblogs.com/wyboooo/p/9744977.html

时间: 2024-10-10 10:03:44

CH5103 传纸条【线性dp】的相关文章

[Luogu P1006]传纸条 (网格DP)

题面 传送门:https://www.luogu.org/problemnew/show/P1006 Solution 挺显然但需要一定理解的网络(应该是那么叫吧)DP 首先有一个显然但重要的结论要发现:从左上走到右下再从右下走回左上=从左上走两次到右下 那么接下来可以考虑: 设f[i][j][k][l]为第一次走到了(i,j)第二次走到了(k,l) 在路径不交错为前提下的能取到的最大友好值 转移方程也挺好写的 考虑这种情况能从哪里转移过来就好(i,j)可以从(i-1,j)或(i,j-1)转移过

CH5103 传纸条

题意 5103 传纸条 0x50「动态规划」例题 描述 给定一个 N*M 的矩阵A,每个格子中有一个整数.现在需要找到两条从左上角 (1,1) 到右下角 (N,M) 的路径,路径上的每一步只能向右或向下走.路径经过的格子中的数会被取走.两条路径不能经过同一个格子.求取得的数之和最大是多少.N,M≤50. 输入格式 第一行有2个用空格隔开的整数n和m,表示有n行m列(1<=n,m<=50). 接下来的n行是一个n*m的矩阵,每行的n个整数之间用空格隔开. 输出格式 一个整数,表示答案. 样例输入

codevs——1169 传纸条(棋盘DP)

2008年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是,他们可以通过传纸条来进行交流.纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,

【NOIP】【codevs】【DP】1169传纸条

呜呜呜这题太虐心了呜呜呜,花了整整两天的时间才把错误找出来,多亏了电子科大的两位金牌的指导... 题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是,他们可以通过传纸条来进行交流.纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n).从小渊传到小轩的纸条只可以向下或者向右

蓝桥杯 - 传纸条 (双线程DP)

题目传送:传纸条 思路:双线程DP,具体看代码; AC代码: #include <map> #include <set> #include <cmath> #include <deque> #include <queue> #include <stack> #include <cstdio> #include <cctype> #include <string> #include <vecto

nyoj 61——传纸条(一)——————【双线dp】

传纸条(一) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是,他们可以通过传纸条来进行交流.纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n).从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者

【日常学习】【棋盘DP】【多线程DP】codevs1169 传纸条题解

转载请注明出处 [ametake版权所有]http://blog.csdn.net/ametake欢迎来看 这是经典的老题了 来源是08年NOIP提高组 上题目 题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是,他们可以通过传纸条来进行交流.纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵

TYVJ 1011 传纸条(双线程DP)

P1011 传纸条 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是,他们可以通过传纸条来进行交流.纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n).从小渊传到小轩的纸条

CodeVS1169 传纸条 [DP补完计划]

题目传送门 题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是,他们可以通过传纸条来进行交流.纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n).从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递. 在活动进行中,小渊希望给小轩传递一