洛谷P7074 [CSP-J2020] 方格取数——题解

[CSP-J2020] 方格取数

一道dp题。难度不大,但是个典型的dp考法,值得一说。

看一眼题,容易写出dp方程ans[i][j]=max{ans[i-1][j],ans[i][j-1],ans[i+1][j]}+val[i][j]。但发现难以确定dp递推的顺序。但思考一会后,又发现dp方程可拆分成两种情况,因为不能走重复的格子,所以对于当前的格子(i,j),要么从上方、左边走过来,且同一列的路径格子的进入方式也为上方/左边;要么从下方、左边走过来,且同一列的路径格子的进入方式也为下方/左边。即dp状态转移可拆分成两种情况,且在其中一种情况中,转移方程都一样。拆分后容易找到明显的转移顺序,最后再合并一下就好。

 1 #include<iostream>
 2 #include<cstdio>
 3 
 4 using namespace std;
 5 
 6 const int N=1e3+5;
 7 const long long FINF=-20000000000ll;
 8 
 9 int n,m;
10 
11 long long up[N][N],down[N][N],ans[N][N],mp[N][N];
12 
13 inline int read()//Z 
14 {
15     int x=0;
16     char ch=getchar();
17     bool f=0;
18     while(!isdigit(ch))
19         f|=ch=='-',ch=getchar();
20     while(isdigit(ch))
21         x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
22     return f?-x:x;
23 }
24 
25 int main()
26 {
27     n=read(),m=read();
28     for(int i=1;i<=n;++i)
29         for(int j=1;j<=m;++j)
30             mp[i][j]=read();
31     for(int i=1;i<=n;++i)
32         ans[i][1]=ans[i-1][1]+mp[i][1];
33     for(int j=2;j<=m;++j)
34     {
35         up[0][j]=down[n+1][j]=FINF;
36         for(int i=1;i<=n;++i)
37             up[i][j]=max(up[i-1][j],ans[i][j-1])+mp[i][j];
38         for(int i=n;i>=1;--i)
39             down[i][j]=max(down[i+1][j],ans[i][j-1])+mp[i][j];
40         for(int i=1;i<=n;++i)
41             ans[i][j]=max(up[i][j],down[i][j]);
42     }
43     printf("%lld",ans[n][m]);
44     return 0;
45 } 
AC代码

 

posted @ 2021-01-25 10:31  千叶繁华  阅读(630)  评论(0)    收藏  举报