http://acm.hust.edu.cn/vjudge/contest/126699#problem/E
题意:共有两个人,一个人A要求从(1, 1)走到(n, n)(只能向右或向下),另一个人B要求从(n, 1)走到(1, n)(只能向右或向上)。相遇时的格子的数值不算(只能相遇一个格子),问你两个人当都到达要求时的地点,最大数值为多少?
分析:先列举一个相遇时的格子,那么共有两种情况。(一种一个人从相遇点的左边过来,另一个人从相遇点的下面过来;另一种一个人从相遇点的上面过来,另一个人从相遇点的 右边过来)如图所示。
方法:求出每个相遇点到四个角的最大值,每个点分别在两种情形下四个dp相加的最大值即为所求
图 A 图 B
#include <iostream> #include <stdio.h> #include <string.h> #include <string> #include <vector> #include <algorithm> #include <map> #include <queue> #include <stack> #include <math.h> using namespace std; #define oo 0x3f3f3f3f const int maxn = 1100; typedef long long LL; int dp1[maxn][maxn], dp2[maxn][maxn], dp3[maxn][maxn], dp4[maxn][maxn], a[maxn][maxn]; int main() { int n, m; while(scanf("%d %d", &n, &m)!=EOF) { for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) scanf("%d", &a[i][j]); } memset(dp1, 0, sizeof(dp1)); memset(dp2, 0, sizeof(dp2)); memset(dp3, 0, sizeof(dp3)); memset(dp4, 0, sizeof(dp4)); ///左上 for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { dp1[i][j] = max(dp1[i-1][j], dp1[i][j-1])+a[i][j]; } } ///右上 for(int i=1; i<=n; i++) { for(int j=m; j>=1; j--) { dp2[i][j] = max(dp2[i-1][j], dp2[i][j+1])+a[i][j]; } } ///左下 for(int i=n; i>=1; i--) { for(int j=1; j<=m; j++) { dp3[i][j] = max(dp3[i+1][j], dp3[i][j-1])+a[i][j]; } } ///右下 for(int i=n; i>=1; i--) { for(int j=m; j>=1; j--) { dp4[i][j] = max(dp4[i+1][j], dp4[i][j+1])+a[i][j]; } } ///注意i,j的范围,因为两者的起点以及终点不能当做相遇的点 int ans = 0; for(int i=2; i<n; i++) { for(int j=2; j<m; j++) { ans = max(ans, dp1[i][j-1]+dp2[i-1][j]+dp3[i+1][j]+dp4[i][j+1]);///对应图A ans = max(ans, dp1[i-1][j]+dp2[i][j+1]+dp3[i][j-1]+dp4[i+1][j]);///对应图B } } printf("%d ", ans); } return 0; }