AcWing 275 传纸条 (dp)

题目链接:https://www.acwing.com/problem/content/description/277/

确定步数和横坐标以后,纵坐标是可以计算出来的,
所以设 (dp[i][j][k]) 表示走了 (i) 步,横坐标分别为 (j, k) 时的最大值,
转移时注意将走到同一格子的情况排除

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;

int n, m; 
int a[55][55], dp[110][55][55];

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	n = read(), m = read();
	for(int i = 1 ; i <= n ; ++i){
		for(int j = 1 ; j <= m ; ++j){
			a[i][j] = read();
		}
	}
	
	dp[2][1][1] = 0;
	for(int i = 3 ; i <= n + m ; ++i){
		for(int j = 1 ; j <= min(n, i) ; ++j){
			for(int k = 1 ; k <= min(n, i) ; ++k){
				if(j == k && i != n + m) continue;
				dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k - 1] + a[j][i - j] + a[k][i - k]);
				if(j - 1 != k || i - 1 == 2) dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k] + a[j][i - j] + a[k][i - k]);
				if(j != k - 1 || i - 1 == 2) dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k - 1] + a[j][i - j] + a[k][i - k]);
				dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k] + a[j][i - j] + a[k][i - k]);
			}
		}
	}
	
	printf("%d
", dp[n + m][n][n]);
	
	return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/14107170.html