1. 程式人生 > 資訊 >蘋果線 + 安卓線 + 20000mAh:臺電快充移動電源 69 元狂促

蘋果線 + 安卓線 + 20000mAh:臺電快充移動電源 69 元狂促

一個很經典的題目了,以前沒有學過dp感覺寫的不明所以然,現在我覺得懂了吧...

閆式分析法我覺得我用的很奇怪,具體奇怪在哪我也說不上來,但我自己習慣於一種思考方式:

先上題目吧:

給定一個如下圖所示的數字三角形,從頂部出發,在每一結點可以選擇移動至其左下方的結點或移動至其右下方的結點,一直走到底層,要求找出一條路徑,使路徑上的數字的和最大。

        7
      3   8
    8   1   0
  2   7   4   4
4   5   2   6   5

輸入格式

第一行包含整數nn,表示數字三角形的層數。

接下來nn行,每行包含若干整數,其中第ii行表示數字三角形第i

i層包含的整數。

輸出格式

輸出一個整數,表示最大的路徑數字和。

資料範圍

1n5001≤n≤500,
1000010000−10000≤三角形中的整數≤10000

輸入樣例:

5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5

輸出樣例:

30
這題一看就知道是dp題,不過做題目不能硬做,要分析了之後再寫
比如在考慮狀態轉移方程的時候,從上到下考慮還是從下往上考慮,從上往下考慮的時候邊界還要特判,很麻煩,所以優先考慮從下到上的順序
對於我自己來說,首先是確立狀態轉移方程,就是令dp【i】或者dp【i】【j】代表了什麼含義
比如這個題的f[i][j]代表了路徑的最優解也就是最大值,之前的過河卒的dp[i][j]代表了到i,j這個點路徑之和,還有昨天存錢的問題dp[i]代表了存到某個數的次數
揹包問題那就更是經典。我說的這些好像就是y總說的集合的概念??
然後開始寫狀態轉移方程了,這個就有很多種情況了,有類似於遞推的過程,有類似於揹包的一些問題
比如對應剛剛的問題,dp【i】【j】可以從左下和右下得到,然後每次得到時求最大值,過河卒就是感覺直接的遞推了,每個座標都由左和上得到,一共是x+y
存錢問題這個就好經典啊,dp[i]可以由dp[i-1]得到,可以由一個數加上6的次方之後得到,可以由一個數加上9的次方數得到。這些狀態轉移方程不就有了麼
寫的時候思路不是太清楚,諒解啊
#include<iostream>
using namespace std;
const int N=510;
int f[N][N],w[N][N];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            cin>>w[i][j];
        }
    }
    for(int i=1;i<=n;i++) f[n][i]=w[n][i];//初始化
for(int i=n-1;i>0;i--)//最後一行賦初值了,為最後一行的最大值,此時從n-1行開始 { for(int j=1;j<=i;j++) { f[i][j]=max(f[i+1][j]+w[i][j],f[i+1][j+1]+w[i][j]); } } cout<<f[1][1]<<endl; return 0; }

就根據這道題咱們來分析一下:

首先令dp[i][j]為到達(i,j)這個座標的最大值,類似於遞推吧,然後從下到上遞推(i,j)這個點可以由(i+1,j)和(i+1,j+1)兩個點得到。然後類似的...我覺得分析到這邊已經可以了...

加油吧!