Re0:DP学习之路 数塔 HDU - 2084(基础递推)

解法

首先是输入的问题,输入的时候还要注意每一层都有多少个

然后是怎么求解,一般求解首先要考虑顺序,是正序还是倒序

如果这个题是正序的话那么最终还需要将最后一行进行一次找max的运算

如果是倒序的话那么最终归于同一个起点,直接进行输出即可

转移方程

转移方程考虑把问题分散化,分散成小的问题,其中这个题的问题就是如果要找最大的,那么每一个数的下面两个相邻的数应该取最大的

所以就是dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+num[i][j]

如果要进行正推,那么应该是每一个数上面和左边的数的最大值加当前的数那么转移方程就是dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+num[i][j]

所以转移方程为

倒推

dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+num[i][j]

正推

dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+num[i][j]

代码

倒推

#include <bits/stdc++.h>
using namespace std;
int dp[1000][1000],num[1000][1000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int t;
  cin>>t;
  while(t--)
  {
    int n;
    cin>>n;
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;i++)
    for(int j=1;j<=i;j++)
    cin>>num[i][j];
    for(int i=n;i>=1;i--)
    for(int j=1;j<=i;j++)
    dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+num[i][j];
    cout<<dp[1][1]<<"\n";
  }
}

正推

#include <bits/stdc++.h>
using namespace std;
int dp[1000][1000],num[1000][1000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int t;
  cin>>t;
  while(t--)
  {
    int n,maxn=-1;
    cin>>n;
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;i++)
    for(int j=1;j<=i;j++)
    cin>>num[i][j];
    for(int i=1;i<=n;i++)
    for(int j=1;j<=i;j++)
    dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+num[i][j];
    for(int i=1;i<=n;i++)
    maxn=max(maxn,dp[n][i]);
    cout<<maxn<<"\n";
  }
}

猜你喜欢

转载自www.cnblogs.com/baccano-acmer/p/10223489.html