Likecloud - eat, eat, eat

Keywords: C++ Dynamic Programming

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;
}

Posted by ajlisowski on Wed, 06 Oct 2021 18:02:43 -0700