蓝桥杯 算法训练 ALGO-36 传纸条

算法训练 传纸条

时间限制:1.0s   内存限制:512.0MB

问题描述

  小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。
  在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。
  还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用0表示),可以用一个0-100的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度只和最大。现在,请你帮助小渊和小轩找到这样的两条路径。

输入格式

  输入第一行有2个用空格隔开的整数m和n,表示班里有m行n列(1<=m,n<=50)。
  接下来的m行是一个m*n的矩阵,矩阵中第i行j列的整数表示坐在第i行j列的学生的好心程度。每行的n个整数之间用空格隔开。

输出格式

  输出一行,包含一个整数,表示来回两条路上参与传递纸条的学生的好心程度之和的最大值。

样例输入

3 3
0 3 9
2 8 5
5 7 0

样例输出

34

数据规模和约定

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

题目解析:

  本道题需用到的算法为动态规划

  题目中提到在 m 行 n 列且带有权值的矩阵中从(1,1)到(m,n)找一条路径,然后再从(m,n)到(1,1)找一条路径,这两天路径不能重复,即每个点只能两个人只能走一次,且不可以回退,即第一条只能向下或向右,第二条只能向上或向左。化简后可知:其实就是从(1,1)到(m,n)找两条路径,这两条路径只能向下或向右且不相交,计算出这两条路径的权值和的最大值即可。

  所以很容易构想出动态规划方程:

  两个人走,利用四维的数组 dp[x1][y1][x2][y2] 来保存路径中间过程的权值之和的最大值,其中 x1 y1 x2 y2 分别表示两个人的位置。

  每个人现在的位置都有两种可能:从他的上边或左边;两个人组合就有四种可能,因此:构造出动态规划方程(map[x][y] 表示权值,即好心程度):

dp[x1][y1][x2][y2] = max(dp[x1-1][y1][x2-1][y2], dp[x1][y1-1][x2-1][y2], dp[x1][y1-1][x2][y2-1], dp[x1-1][y1][x2][y2-1]) + map[x1][y1] + map[x2][y2];

  其中 x1,x2 的取值范围为从起点到终点,即 1 ~ m,y1,y2 的取值范围为起点到终点,即 1 ~ n。

  此方程的时间复杂度为 O(n4)。因此可以进一步优化:

  假如现在是 5 x 5 的矩阵,每个人从起点走三步,会出现四种情况。


  这四种情况的坐标分别为:(0,3)(1,2) (2,1) (3,0)。通过这四个坐标,发现一个规律: 0 + 3 = 1 + 2 = 2 + 1 = 3 + 0 = 3 = k (k为走的步数)。所有,x1 + x2 = k , x2 + y2 = k。所以,y = k - x。因此,三维的动态规划方程为:

dp[k][x1][x2]=max(dp[k-1][x1][x2],dp[k-1][x1-1][x2-1],dp[k-1][x1-1][x2],dp[k-1][x1][x2-1])+map[x1][k-x1]+map[x2][k-x2];

  其中,dp[k][x1][x2] 就是四维的 dp[x1][y1][x2][y2],dp[k-1][x1][x2] 就是四维的 dp[x1][y1-1][x2][y2-1],map[x1][k-x1] 就是四维的 dp[x1][y1],以此类推。

  终点的坐标为 (m-1,n-1),但是 k 不能到达终点这个位置,因为违背了题目中两个人不能重复,k 的最大情况为(m-1)+(n-1)- 1,k 在最小情况也就是 2 x 2 的矩阵中取得最小值 1,所以 k 的取值范围为 1 ~  m+n-3。x1 和 x2 的取值范围都为从起点(0,0)到最大步数 k,即 0 ~ k。

  此方程的时间复杂度为 O(n3)。因此还可以进一步优化:

  从三维的动态规划方程可以发现,前一步总是 k - 1,所以,二维的动态规划方程可以优化为:

dp[x1][x2] = max(dp[x1][x2], dp[x1 - 1][x2 - 1], dp[x1 - 1][x2], dp[x1][x2 - 1]) + map[x1][k - x1] + map[x2][k - x2];

  根据三维时的分析,两条路径都走不到终点,所以让第一个人走到终点的上方,第二个人走到终点的左方,k 的取值范围为 1 ~ (m-1)+(n-1)- 1,最终要输出的结果为 dp[m-2][m-1]。

  此方程的时间复杂度为 O(n2)。

示例代码1 [四维数组]:

 1 #include <iostream>
 2 #include<stdio.h>
 3 #include<cmath>
 4 using namespace std;
 5
 6 #define MAX_NUM 52
 7
 8 int map[MAX_NUM][MAX_NUM];     //好心程度 | 权值
 9 int dp[MAX_NUM][MAX_NUM][MAX_NUM][MAX_NUM];
10
11 int maxPath(int m, int n)
12 {
13     for (int x1 = 1; x1 <= m; x1++)
14     {
15         for (int y1 = 1; y1 <= n; y1++)
16         {
17             for (int x2 = 1; x2 <= m; x2++)
18             {
19                 for (int y2 = 1; y2 <= n; y2++)
20                 {
21                     /*
22                         如果第一个人没有走到最后一行或最后一列,并且两个人没有重复
23                         因为走到最后一行或最后一列,容易造成第二个人无路可走的情况
24                     */
25                     if ((x1 < m || y1 < n) && x1 == x2 && y1 == y2)
26                     {
27                         continue;
28                     }
29                     dp[x1][y1][x2][y2] = max( max(dp[x1-1][y1][x2-1][y2], dp[x1-1][y1][x2][y2-1]),
30                                               max(dp[x1][y1-1][x2-1][y2], dp[x1][y1-1][x2][y2-1]))
31                                              + map[x1][y1] + map[x2][y2];
32                 }
33             }
34         }
35     }
36     return dp[m][n][m][n];
37 }
38
39 int main()
40 {
41     int m, n;
42     scanf("%d%d", &m, &n);
43
44     for (int i = 1;i <= m; i++)
45         for (int j = 1;j <= n; j++)
46             scanf("%d", &map[i][j]);
47
48     int ans = maxPath(m, n);
49     printf("%d\n", ans);
50
51     return 0;
52 }

示例代码2 [三维数组]:

 1 #include <iostream>
 2 #include<cmath>
 3 using namespace std;
 4
 5 #define MAX_NUM 52
 6
 7 int map[MAX_NUM][MAX_NUM];     //好心程度 | 权值
 8 int dp[MAX_NUM+MAX_NUM][MAX_NUM][MAX_NUM];
 9
10 int maxPath(int m, int n)
11 {
12     for (int k = 1;k <= m+n-3; k++)
13     {
14         for (int x1 = 0; x1 <= k; x1++)
15         {
16             for (int x2 = 0; x2 <= k; x2++)
17             {
18                 if (x1 == x2)    //x1 == x2 相当于(x1 == x2 && y1 = y2)
19                 {
20                     continue;
21                 }
22                 dp[k][x1][x2] = max(max(dp[k-1][x1][x2], dp[k-1][x1-1][x2-1]),
23                                     max(dp[k-1][x1-1][x2], dp[k-1][x1][x2-1]))
24                                 + map[x1][k-x1] + map[x2][k-x2];
25             }
26         }
27     }
28     return dp[m+n-3][m-1][m-2];
29 }
30
31 int main()
32 {
33     int m, n;
34     scanf("%d%d", &m, &n);
35
36     for (int i = 0; i < m; i++)
37         for (int j = 0; j < n; j++)
38             scanf("%d", &map[i][j]);
39
40     int ans = maxPath(m, n);
41     printf("%d\n", ans);
42
43     return 0;
44 }

示例代码3 [二维数组]:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 using namespace std;
 5
 6 #define MAX_NUM 52
 7
 8 int map[MAX_NUM][MAX_NUM];   //好心程度 | 权值
 9 int dp[MAX_NUM][MAX_NUM];
10
11 int maxPath(int m, int n)
12 {
13
14     for (int k = 1; k <= m+n-3; k++)
15     {
16         for (int x1 = m-1; x1 >= 0; x1--)
17         {
18             for (int x2 = m-1; x2 > x1; x2--)
19             {
20                 if ( k >= x1 && k >= x2)    //x + y = k,当k >= x时,说明还在矩阵范围之内
21                 {
22                     dp[x1][x2] = max(max(dp[x1][x2], dp[x1-1][x2-1]),
23                                      max(dp[x1-1][x2], dp[x1][x2-1]))
24                                  + map[x1][k-x1] + map[x2][k-x2];
25                 }
26             }
27         }
28     }
29     return dp[m-2][m-1];
30 }
31
32 int main()
33 {
34     int m, n;
35     scanf("%d %d", &m, &n);
36
37     for (int i = 0;i < m; i++)
38         for (int j = 0; j < n; j++)
39             scanf("%d", &map[i][j]);
40
41     int ans = maxPath(m, n);
42     printf("%d\n", ans);
43
44     return 0;
45 }
时间: 2024-11-05 02:28:55

蓝桥杯 算法训练 ALGO-36 传纸条的相关文章

蓝桥杯——算法训练之乘积最大

问题描述 今年是国际数学联盟确定的"2000--世界数学年",又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加.活动中,主持人给所有参加活动的选手出了这样一道题目: 设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大. 同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子: 有一个数字串:312, 当N=3,K=1时

蓝桥杯 算法训练 ALGO-124 数字三角形

算法训练 数字三角形 时间限制:1.0s   内存限制:256.0MB 问题描述 (图3.1-1)示出了一个数字三角形. 请编一个程序计算从顶至底的某处的一条路 径,使该路径所经过的数字的总和最大. ●每一步可沿左斜线向下或右斜线向下走: ●1<三角形行数≤100: ●三角形中的数字为整数0,1,-99: . (图3.1-1) 输入格式 文件中首先读到的是三角形的行数. 接下来描述整个三角形 输出格式 最大总和(整数) 样例输入 573 88 1 02 7 4 44 5 2 6 5 样例输出 3

蓝桥杯 算法训练 ALGO-125 王、后传说

算法训练 王.后传说 时间限制:1.0s   内存限制:256.0MB 问题描述 地球人都知道,在国际象棋中,后如同太阳,光芒四射,威风八面,它能控制横.坚.斜线位置. 看过清宫戏的中国人都知道,后宫乃步步惊心的险恶之地.各皇后都有自己的势力范围,但也总能找到相安无事的办法. 所有中国人都知道,皇权神圣,伴君如伴虎,触龙颜者死...... 现在有一个n*n的皇宫,国王占据他所在位置及周围的共9个格子,这些格子皇后不能使用(如果国王在王宫的边上,占用的格子可能不到9个).当然,皇后也不会攻击国王.

蓝桥杯 算法训练 ALGO-139 s01串

算法训练 s01串 时间限制:1.0s 内存限制:256.0MB 问题描述  s01串初始为"0"  按以下方式变换  0变1,1变01 输入格式  1个整数(0~19) 输出格式  n次变换后s01串 样例输入 3 样例输出 101 数据规模和约定  0~19 示例代码: 1 import java.util.Scanner; 2 3 public class Main { 4 static StringBuffer sb = new StringBuffer(); 5 public

蓝桥杯 算法训练 ALGO-57 删除多余括号

算法训练 删除多余括号 时间限制:1.0s   内存限制:512.0MB 问题描述 从键盘输入一个含有括号的四则运算表达式,要求去掉可能含有的多余的括号,结果要保持原表达式中变量和运算符的相对位置不变,且与原表达式等价,不要求化简.另外不考虑'+' '-'用作正负号的情况,即输入表达式不会出现(+a)或(-a)的情形. 输入格式 表达式字符串,长度不超过255, 并且不含空格字符.表达式中的所有变量都是单个小写的英文字母, 运算符只有加+减-乘*除/等运算符号. 输出格式 去掉多余括号后的表达式

蓝桥杯 算法训练 ALGO-156 表达式计算

算法训练 表达式计算 时间限制:1.0s   内存限制:256.0MB 问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的值. 样例输入 1-2+3*(4-5) 样例输出 -4 数据规模和约定 表达式长度不超过100,表达式运算合法且运算过程都在int内进行. 题目解析: 运算优先级: 括号 → 乘除 → 加减 例如 1-2+3*(4-5) (1)计算(4-5),表达式变为  1-2+3*-1 (2

蓝桥杯 算法训练 ALGO-50 数组查找及替换

算法训练 数组查找及替换 时间限制:1.0s   内存限制:512.0MB 问题描述 给定某整数数组和某一整数b.要求删除数组中可以被b整除的所有元素,同时将该数组各元素按从小到大排序.如果数组元素数值在A到Z的ASCII之间,替换为对应字母.元素个数不超过100,b在1至100之间. 输入格式 第一行为数组元素个数和整数b 第二行为数组各个元素 输出格式 按照要求输出 样例输入 7 2 77 11 66 22 44 33 55 样例输出 11 33 55 M 示例代码: 1 #include<

蓝桥杯 算法训练 ALGO-15 旅行家的预算

算法训练 旅行家的预算 时间限制:1.0s   内存限制:256.0MB 问题描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离D1.汽车油箱的容量C(以升为单位).每升汽油能行驶的距离D2.出发点每升汽油价格P和沿途油站数N(N可以为零),油站i离出发点的距离Di.每升汽油价格Pi(i=1,2,--N).计算结果四舍五入至小数点后两位.如果无法到达目的地,则输出"No Solution". 输入格式 第一行为4个实数D1.C.

蓝桥杯 算法训练 ALGO-108 最大的体积

算法训练 最大体积 时间限制:1.0s   内存限制:256.0MB 问题描述 每个物品有一定的体积(废话),不同的物品组合,装入背包会战用一定的总体积.假如每个物品有无限件可用,那么有些体积是永远也装不出来的.为了尽量装满背包,附中的OIER想要研究一下物品不能装出的最大体积.题目保证有解,如果是有限解,保证不超过2,000,000,000 如果是无限解,则输出0 输入格式 第一行一个整数n(n<=10),表示物品的件数 第2行到N+1行: 每件物品的体积(1<= <=500) 输出格