Problem H: 方格取数
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 28 Solved: 9
Description
有N * N个格子,每个格子里有正数或者0,从最左上角往最右下角走,只能向下和向右,一共走两次(即从左上角走到右下角走两趟),把所有经过的格子的数加起来,求最大值SUM,且两次如果经过同一个格子,则最后总和SUM中该格子的计数只加一次。
Input
第一行N(1 <= N <= 100)
然后N行,每行N个数。依次表示N * N每个格子的数值。(0 <= value <= 1000) ;
Output
输出最大值SUM。
Sample Input
Sample Output
HINT
Hint
Possible Way:
第一次 1 -> 2 -> 2 -> 4 -> 2
第二次 1 -> 2 -> 3 -> 1 -> 2
SUM = 15
思路:
DP。一共走两次,可以看成两个人同时从起点走向终点。每个点都可以从上面或者左边得到,所以两个人同时走的话,可以有四种组合。故可以得到转移方程:
Dp [ X1 ] [ Y1 ] [ X2 ] [ Y2 ] = max (Dp [ X1 - 1 ] [ Y1 ] [ X2 - 1 ] [ Y2 ] ,
Dp [ X1 - 1 ] [ Y1 ] [ X2 ] [ Y2 - 1 ] ,
Dp [ X1 ] [ Y1 - 1 ] [ X2 - 1 ] [ Y2 ] ,
Dp [ X1 ] [ Y1 - 1 ] [ X2 ] [ Y2 - 1 ] )+ Map [ X1 ] [ Y1 ] + Map [ X2 ] [ Y2 ];
四个循环,范围为 1 ~ 100,那么时间复杂度 O(n ^ 4)会造成 TLE,所以还要进一步优化。用 k 代表步数,那么转移方程可以变为:
Dp [ k ] [ X1 ] [ X2 ] = max (Dp [ k - 1 ] [ X1 - 1 ] [ X2 - 1 ] ,
Dp [ k - 1 ] [ X1 - 1 ] [ X2 ] ,
Dp [ k - 1 ] [ X1 ] [ X2 - 1 ] ,
Dp [ k - 1 ] [ X1 ] [ X2 ] ) + Map [ X1 ] [ k - X1 ] + Map [ X2 ] [ k - X2 ];
这样的话时间复杂度降为 O (n ^ 3 )就不会导致TLE了。
如何避免走相同的格的时候只加一次呢?
因为 k 是一样的,说明当 x1 == x2 的时候,y1 == y2,这时候两个走在了同一格,所以只要判断是否 x1 == x2 就能决定要不要加两次了。若题目要求改为不允许走过同一点,将 x1 == x2 时候 continue 就可以了。
AC:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int dp[210][105][105]; int Map[105][105]; int main () { int n, sum; scanf("%d", &n); for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) scanf("%d", &Map[i][j]); sum = n + n - 2; for (int k = 0; k <= sum; ++k) { for (int x1 = 0; x1 < n; ++x1) { for (int x2 = 0; x2 < n; ++x2) { int ans = 0; int y1 = k - x1, y2 = k - x2; if (k > 0 && x1 > 0 && x2 > 0) ans = max(ans, dp[k - 1][x1 - 1][x2 - 1]); if (k > 0 && x1 > 0 && y2 > 0) ans = max(ans, dp[k - 1][x1 - 1][x2]); if (k > 0 && y1 > 0 && x2 > 0) ans = max(ans, dp[k - 1][x1][x2 - 1]); if (k > 0 && y1 > 0 && y2 > 0) ans = max(ans, dp[k - 1][x1][x2]); if (y1 < 0 || y2 < 0) continue; dp[k][x1][x2] = ans + Map[x1][y1] + (x1 == x2 ? 0 : Map[x2][y2]); } } } printf("%d\n", dp[sum][n - 1][n - 1]); return 0; }
相关推荐
方格取数系列算法分析 本文将对方格取数系列算法进行分析,讨论动态规划算法和穷举算法在解决此问题时的优缺点。 首先,从问题的描述中可以看到,我们需要从 A 点出发,走两次到达 B 点,并取得的数之和为最大。...
【标题】"方格取数.zip"对应的是一组与编程竞赛相关的资源,特别是与"蓝桥杯"这一知名编程赛事紧密相连。蓝桥杯比赛主要考察参赛者的程序设计能力和算法运用技巧,是针对计算机科学和技术专业学生的重要竞赛之一。在...
首先,我们可以将问题看作两个人同时从左上角走到右下角并且进行取数操作。设左上角坐标为(1,1),右下角坐标为(n,n),将第x行第y列的格子记为(x,y)。按下图中虚线虚线所示划分阶段,可以看到:处于第i阶段上的...
11. **方格取数**: - 这类问题通常涉及寻找最大和的同时避免相邻单元格的选取,可能需要利用位运算进行状态编码和转换。 12. **找数问题**: - **找出现奇数次的数**:可以使用异或运算在O(n)时间复杂度内找到...
【方格取数1】是一种基于算法的训练题目,主要涉及动态规划和回溯搜索的策略。该问题的核心是寻找两条路径,从图的左上角出发(A点,坐标为(1,1))到达右下角(B点,坐标为(N,N)),并且在两次行走中最大化路径上...
CSP-J复赛集训200分-300分必刷-csp-j-2020方格取数
洛谷题目AC源代码
n*m方格数的计算n*m方格数的计算n*m方格数的计算n*m方格数的计算
如下的10个格子 +--+--+--+ | | | | +--+--+--+--+ ...一共有多少种可能的填数方案? 请填写表示方案数目的整数。 注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。 答案:1580
- **知识点概述**:方格取数问题是信息学竞赛中一个经典的题目类型,通常涉及到在一维或二维数组中寻找满足某些条件的最大子序列或子矩阵的值。 - **核心思想**:动态规划是解决此类问题的有效方法之一。通过对每个...
黄金分割数,也称为黄金比例,是数学中非常重要的无理数,其数值约为0.***...,在自然界、艺术和建筑学中广泛存在,历史上也激发了无数科学家和数学家进行研究。黄金分割数的高精度计算对于这些研究工作具有非常重要...
舒尔特方格是一种经典的注意力训练工具,源自德国心理学家舒尔特的研究,它通过让孩子们按顺序找出方格中的数字来锻炼他们的注意力集中能力。这个"舒尔特方格excel自动生成.rar"压缩包提供了一个Excel脚本来自动生成...
舒尔特方格是一款经典的注意力训练游戏,源自德国心理学家舒尔特的研究,它通过让玩家按顺序点击随机分布的数字来提升专注力和反应速度。在这个“舒尔特方格android源码”中,我们可以深入理解如何在Android平台上...
"方格网计算程序"是一种在土木工程领域中常用的方法,主要用于估算场地平整或填挖土石方的工程量。这种技术通过将施工区域划分为一系列相等大小的正方形网格,然后对每个网格进行高程分析,以确定每个方格的土方量。...
在软件设计实践课上关于方格旋转填数字的代码.通过循环嵌套解决问题
根据给定的信息,本文主要涉及两个核心主题:一是与“1749数字方格”相关的编程题目及其解决方案;二是围绕计算机科学与技术(CSP-J NOIP 信奥)的相关知识点。 ### 1749数字方格 #### 题目背景 “1749数字方格”...
### C#窗体动态生成小方格 #### 知识点概述 本文将详细介绍如何使用C#在Windows Forms应用程序中动态生成小方格,并通过鼠标点击事件改变这些方格的状态。这种方法利用了重载的方式获取窗体上的坐标,并在相应坐标...
舒尔特方格是一种训练专注力和视觉搜索能力的心理学工具,源于德国心理学家舒尔特的研究。这个训练方法通过在一张方形纸上排列数字,要求参与者按照数字顺序快速且准确地指出它们,以此来提高注意力集中和反应速度。...
对于其他位置,到达(i, j)的路径数等于到达(i-1, j)和到达(i, j-1)的路径数之和,即dp[i][j] = dp[i-1][j] + dp[i][j-1]。 组合数学在这里主要体现在计算可能的路径数量上。例如,如果网格大小为m×n,那么从左上角...
舒尔特方格是一种训练注意力和提高反应速度的心理学训练工具,由德国心理学家舒尔特在20世纪50年代提出。它是由一个方形的矩阵组成,通常为5x5、10x10或者更大,矩阵中的每个单元格内都有一个数字,数字顺序随机分布...