CF B. Working out dp 递推

来源:互联网 发布:劳动法律师事务所知乎 编辑:程序博客网 时间:2024/05/16 01:40

CF dp 递推

题意:

​ 给出nxm个数字矩阵,求出从左上角到右下角的最大权值和,权值就是数字,求出从左下到右上的最大权值和,当然两条路只能交叉一个位置,并且此位置上的权值不能算入和。求出两条路的最大权值和。

思路:

  • 注意边界不能作为交叉位置。

终极思想是枚举相叉位置,知道位置之后只需求出每一条路是怎么走的就行,很容易得出只有两种走法,别想太多,试试就知道。那么四种走法dp求出既可。

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 1005;int dp[maxn][maxn][4];int a[maxn][maxn];int main(){//    freopen("in.txt","r",stdin);    int n,m;    scanf("%d%d",&n,&m);    for(int i = 1;i <= n; i++) {        for(int j = 1;j <= m; j++) {            scanf("%d",&a[i][j]);        }    }    for(int i = 1;i <= n; i++) {        for(int j = 1;j <= m; j++) {            dp[i][j][0] = a[i][j] + max(dp[i][j-1][0],dp[i-1][j][0]);        }    }    for(int i = n;i >= 1; i--) {        for(int j = m;j >= 1; j--) {            dp[i][j][1] = a[i][j] + max(dp[i+1][j][1],dp[i][j+1][1]);        }    }    for(int i = n;i >= 1; i--) {        for(int j = 1;j <= m; j++) {            dp[i][j][2] = a[i][j] + max(dp[i+1][j][2],dp[i][j-1][2]);        }    }    for(int i = 1;i <= n; i++) {        for(int j = m;j >= 1; j--) {            dp[i][j][3] = a[i][j] + max(dp[i-1][j][3],dp[i][j+1][3]);        }    }    int ans = 0;    for(int i = 2;i < n; i++) {        for(int j = 2;j < m; j++) {            ans = max(ans,dp[i-1][j][0]+dp[i+1][j][1]+dp[i][j-1][2]+dp[i][j+1][3]);            ans = max(ans,dp[i][j-1][0]+dp[i][j+1][1]+dp[i+1][j][2]+dp[i-1][j][3]);        }    }    printf("%d\n",ans);    return 0;}
原创粉丝点击