首页 > 其他分享 >P7074 [CSP-J 2020] 方格取数

P7074 [CSP-J 2020] 方格取数

时间:2023-02-09 11:13:10浏览次数:55  
标签:ch 走法 int max 取数 2020 DP P7074 dp

思路来自大佬:Indjy

学校老师居然把这个题放在区间DP里面但是我没想到该怎样用,标签里也没有,那就用暴力DP来做吧。

题目大意

有一个\(n \times m\)的方格,可以向下,向上,向右走一格,而且不能走重复的格子。

现在要求在一条路径中和最大的走法。

解题思路

因为这个题目比较扯,是向上、向下、向右走,不是我们常见的向下、向左、向右,因此我们想到了一种神奇的方法:

将整个表格顺时针旋转90度

这下就好办了:变成了向下、向左、向右的走法了。

看到这个走法你会想到什么?是不是感觉很熟悉?

没错,那就是数字三角形的走法。因此,这一道普及+/提高-的题一下子变成了普及-。

需要的数组及变量

dp[N][N][2]:顾名思义就是存动态规划。但是,和数字三角形不一样,我们需要多一维来存是向左还是向右。

a[N][N]:存原来的数据(表格)。

nm:题目所给。

设计代码

DP方程

我们既然已经知道了DP方程和数字三角形很类似,那就直接上吧。

我们设\(dp[i][j][0 / 1]\)表示现在的位置是\((i, j)\),0表示向左,1表示向右。

向下走

向下走和之前来的方向没有关系,所以就是看左边还是右边最大然后直接转移。那么方程就是:

\(dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1]) + a[i][j]\),

\(dp[i][j][1] = max(dp[i - 1][j][0], dp[i - 1][j][1]) + a[i][j]\)。

向左走

顾名思义,就是看当前的大还是从左边转移的大。于是方程就是:

\(dp[i][j][0] = max(dp[i][j][0], dp[i][j - 1][0] + a[i][j])\)。

向右走

和向左走一样,方程就是:

\(dp[i][j][1] = max(dp[i][j][1], dp[i][j + 1][1] + a[i][j])\)。

两个方向要分别转移,向左要倒序,向右要正序。

完整代码

#include <bits/stdc++.h>
#define int long long 
#define inf 0x7f7f7f7f7f7f7f
using namespace std;
const int N = 1e3 + 10;
int dp[N][N][2], a[N][N];
int n, m;
int read() {
	int x = 0, w = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			w = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * w;
}
signed main() {
	n = read(); m = read();
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			a[j][i] = read();
	swap(n, m);
	memset(dp, -inf, sizeof dp);
	dp[1][1][0] = dp[1][1][1] = a[1][1];
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (i != 1) {
				dp[i][j][0] = max(dp[i][j][0], max(dp[i - 1][j][0], dp[i - 1][j][1]) + a[i][j]);
				dp[i][j][1] = max(dp[i][j][1], max(dp[i - 1][j][0], dp[i - 1][j][1]) + a[i][j]);
			}
			if (j != 1)
				dp[i][j][0] = max(dp[i][j][0], dp[i][j - 1][0] + a[i][j]);
		}
		for (int j = m; j >= 1; j--) 
			if (j != m)
				dp[i][j][1] = max(dp[i][j][1], dp[i][j + 1][1] + a[i][j]);
	}
	cout << max(dp[n][m][0], dp[n][m][1]) << endl;
	return 0;
}

给个赞吧!

标签:ch,走法,int,max,取数,2020,DP,P7074,dp
From: https://www.cnblogs.com/GTGumiiL/p/17104491.html

相关文章