1. 程式人生 > >Re0:DP學習之路 數塔 HDU - 2084(基礎遞推)

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