1. Main idea of the topic
Title Description
Luogu P1508
Original title
Li Da Buffalo, which is in a certain period, has been in a state of hunger recently because of its relatively developed digestive system. One day in class, just as he was dizzy with hunger, an M suddenly flashed in front of him × n(n,m ≤ 200), and I am just below the midpoint of one side of the large dining table. The dining table is divided into m*n small squares. In each square, there is a huge circular dinner plate filled with food that makes Li buffalo yearn for day and night. Li Da Buffalo has scored all the food on the table according to the energy it can provide (some are negative because he has diarrhea). He decides to eat from his position to the other side of the table, but he has a habit of eating - only the food on the plate in front of him, left front or right front.
Because Li Da buffalo is too hungry to use his brain, and he wants to get the most energy, he handed the problem to you.
The starting point of each group of data is below the middle of the last row!
(note that it starts from any one of (m,n/2) (m,n/2+1) (m,n/2+2))
Input format
The first behavior m n (n is an odd number), Li Da buffalo starts at the bottom of the middle of the last line
Next is the digital range matrix of m*n
There are m rows with n numbers in each row. The numbers are separated by spaces. They represent the energy provided by the food on the plate on the grid
All numbers are integers
Output format
A number is the maximum energy value you find
2. Recursive analysis
The recursion of this question is still very water. Just compare the size of the three cases of left, middle and right directly
formula
d
p
[
x
]
[
y
]
=
m
a
x
(
d
p
[
x
−
1
]
[
y
]
,
m
a
x
(
d
p
[
x
−
1
]
[
y
−
1
]
,
d
p
[
x
−
1
]
[
y
+
1
]
)
)
dp[x][y]=max(dp[x-1][y],max(dp[x-1][y-1],dp[x-1][y+1]))
dp[x][y]=max(dp[x−1][y],max(dp[x−1][y−1],dp[x−1][y+1]))
Consider the boundary (or not):
1.y=1
d
p
[
x
]
[
y
]
=
m
a
x
(
d
p
[
x
−
1
]
[
y
]
,
d
p
[
x
−
1
]
[
y
+
1
]
)
dp[x][y]=max(dp[x-1][y],dp[x-1][y+1])
dp[x][y]=max(dp[x−1][y],dp[x−1][y+1])
2.y=n
d
p
[
x
]
[
y
]
=
m
a
x
(
d
p
[
x
−
1
]
[
y
]
,
d
p
[
x
−
1
]
[
y
−
1
]
)
dp[x][y]=max(dp[x-1][y],dp[x-1][y-1])
dp[x][y]=max(dp[x−1][y],dp[x−1][y−1])
Remember to add your own energy: a[x][y]
3. What about memory search
It should be noted that - 1 cannot be used for initialization of this problem, because there is - 1 in the data (having suffered a loss)
Just mark it with an array of bool type,
Others are similar to recursion?
4. Code implementation
Recurrence
Remember to initialize the top row
for(int i=1;i<=n;i++) dp[1][i]=a[1][i];((initialization) for(int i=2;i<=m;i++){ for(int j=1;j<=n;j++){ if(j!=1&&j!=n)//Recursion actually does not need boundaries (starting from dp[1][1]) dp[i][j]=max(dp[i-1][j],max(dp[i-1][j-1],dp[i-1][j+1]))+a[i][j]; if(j==1) dp[i][j]=max(dp[i-1][j],dp[i-1][j+1])+a[i][j]; if(j==n) dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+a[i][j]; } }
Memory search
int dfs(int x,int y){ if (vis[x][y]) return f[x][y]; for(int i=-1;i<=1;i++) if (y+i>0&&y+i<=n&&x-1>0) f[x][y]=max(f[x][y],dfs(x-1,y+i)+a[x][y]); vis[x][y]=true; return f[x][y]; }
5. Positive solution
a. Recursive code
#include<bits/stdc++.h> using namespace std; #define ll long long ll n,m; ll a[205][205],dp[205][205]; int main(){ cin>>m>>n; for(int i=1;i<=m;i++) for(int j=1;j<=n;j++){ cin>>a[i][j]; } for(int i=1;i<=n;i++) dp[1][i]=a[1][i]; for(int i=2;i<=m;i++){ for(int j=1;j<=n;j++){ if(j!=1&&j!=n)//Recursion actually does not need boundaries (starting from dp[1][1]) dp[i][j]=max(dp[i-1][j],max(dp[i-1][j-1],dp[i-1][j+1]))+a[i][j]; if(j==1) dp[i][j]=max(dp[i-1][j],dp[i-1][j+1])+a[i][j]; if(j==n) dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+a[i][j]; } } ll maxn=-99999999; for(int i=n/2;i<=n/2+2;i++){ maxn=max(dp[m][i],maxn); } cout<<maxn; return 0; }
b. Memorized search code
#include<bits/stdc++.h> using namespace std; int a[202][202],f[202][202]; bool vis[202][202]; int n,m; int maxn(int x,int y,int z){ return max(x,max(y,z)); } int dfs(int x,int y){ if (vis[x][y]) return f[x][y]; for(int i=-1;i<=1;i++) if (y+i>0&&y+i<=n&&x-1>0) f[x][y]=max(f[x][y],dfs(x-1,y+i)+a[x][y]); vis[x][y]=true; return f[x][y]; } int main(){ cin>>n>>m; memset(a,-99999,sizeof(a)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j]; memset(f,-0x3f,sizeof(f)); memset(vis,false,sizeof(vis)); for(int i=1;i<=m;i++) f[1][i]=a[1][i],vis[1][i]=true; dfs(n+1,m/2+1); cout<<maxn(f[n][m/2],f[n][m/2+1],f[n][m/2+2])<<endl; return 0; }