講義 GDFZOJ 38 動態規劃基礎3

2022-05-20 03:19:36 字數 4420 閱讀 9405

更好的閱讀體驗

這是乙個很水的題目,就是乙個斐波那契數列……

設有 \(f\) 陣列,則 \(f_i=f_+f_(f_1=1,f_2=2)\) 。

**:

#includeusing namespace std;

const int n=35;

int f[n]=;

int main()

__________

return 0;

}

如果要抵達距離為 \(x\) 的乙個點,可以從 \(x-y\) 的地方在乘一輛距離為 \(y\) 的車。

於是有狀態轉移方程:\(f_i=\max\+a_j\}\) 。其中 \(a\) 陣列為 \(10\) 公里及以內的車費。

**:

#includeusing namespace std;

const int n=105;

int f[n],a[n];

int main()

int n;

scanf("%d",&n);

for(int i=1; i<=n; i++)

} printf("%d",f[n]);

return 0;

}

我們可以讓這只小豬從 \(0\) 號節點開始跳,跳到 \(n+1\) 號節點。

則有方程:$ f_i=\max(f_i,f_-q+a_i),1\le j\le2$ 。

再判斷一下在跳的過程中的體力值即可。

#includeusing namespace std;

const int n=1e6+5;

int f[n],a[n];

int main()

f[0]=p,f[1]=p-q>=0?p-q+a[1]:-1e9;

for(int i=2; i<=n+1; i++)

if(f[n+1]<=0) else

return 0;

}

我們可以發現:乙個人可以自己買票,也可以和他後面的人買票。

所以有方程:\(f_i=\max(f_+a_i,f_+b_)\) 。

**:

#includeusing namespace std;

const int n=1e6+5;

int f[n],a[n],b[n];

int main()

for(int i=1; i設 \(f_i\) 為前 \(i\) 輛車通過橋的最短時間,設 \(t_\) 第 \(i\) -第 \(j\) 輛車(租車的車隊)通過所需時間。

我們分析方程:

**綜合起來,我們就得到了方程:\(f_i=\min(f_+t_)\),且要滿足\(\sum_^iw_k\le t\) 。

為了降低時間複雜度、程式設計複雜度,我們可以:

預處理重量

定義 \(w_i\) 為前 \(i\) 輛車的總重(即字首和,是處理這類問題非常好的方法,可以降低時間複雜度)。需要知道第 \(j\) 輛車到第 \(i\) 輛車的總重時,用\(w_i-w_\)就可以了;

預處理時間

定義 \(t\) 為橋的全長; \(v_i\) 為第 \(i\) 輛車的速度; \(t_i\) :第 \(i\) 輛車通過橋所需時間; \(t_\) 第 \(i\) 輛車到第 \(j\) 輛車組成的車隊通過橋所需的時間;

\(w\) 陣列、\(v\) 陣列和\(w\) 陣列一定要開 long long,否則兩個較大的 int 相加會炸掉!(雖然此題可能沒有卡 int)。

**:#includeusing namespace std;

using ll=long long;

const ll n=1005;

ll w[n],s[n],sum[n];

double f[n],t[n],a[n][n];

int main()

for(ll i=1; i<=n-1; i++)

} for(ll i=1; i<=n; i++)

printf("%.1lf",f[n]);

return 0;

}

設 \(f_i\) 為前 \(i\) 分鐘能獲得的最大的經驗值。

預設在工作後才能獲得經驗值。容易知道,對於每乙個工作,完成時間的 \(f\) 值就等於開始時間的 \(f\) 值加上工作所獲得的經驗值(裡面取個最大值),即 \(f_=max(f_,f_+p_i)\) 。

但是要注意,對於第 \(i\) 分鐘,它可能不是某個工作的結束時間,即 \(f_i\) 不會被更新。所以在列舉完前乙個的結束狀態時,就要用 \(f_j=\max(f_j,f_)\) 對結果進行遞推。

#includeusing namespace std;

const int n=5005;

struct work

bool operator

} a[n];

int f[n];

int main()

sort(a+1,a+n+1);

________

int ans=0;

for(int i=1; i<=m; i++)

printf("%d",ans);

return 0;

}

首先我們來講解一下他的遞推關係式:\(f_i=\max(f_i,f_j+1)\) 。

定義 \(f_i\) 為:以 \(a_i\) 為末尾的最長上公升子串行的長度。

那麼 \(f_i\) 包含什麼呢?

情況\(1\):只包含它自己,也就是說它前面的元素全部都比他大;

情況2:為了保證上公升子串行盡可能的長,那麼就有 \(f_i\) 盡可能的大,但是再保證 \(f_i\) 盡可能大的基礎上,還必須滿足序列的上公升。所以 \(f_i=\max(1,f_j+1)(j。這裡的 \(1\) 就是當 \(a_i\) 前面的數都比他大的時候,他自己為乙個子串行;\(f_j+1\) 指的是: 當第 \(i\) 個數前面有乙個第 \(j\) 個數滿足 \(a_j並且 \(j這時候就說明 \(a_i\) 元素可以承接在 \(a_j\) 元素後面來盡可能的增加子串行的長度。

將 \(j\) 從 \(1\) 遍歷到 \(i-1\) ,在這之間,找出盡可能大的 \(dp_i\)即為最長上公升子串行的長度。(注意: \(f_n\) 不一定是最長的子串行。)

**。**:

#includeusing namespace std;

const int n=1005;

int a[n],f[n];

int main()

int ans=0;

________

printf("%d",ans);

return 0;

}

顯然這是乙個最長上公升子串行最長下降子串行的有機結合。

求出兩者可連線的數量的最大值,那 \(n\) 去減即可。

**:

#includeusing namespace std;

const int n=205;

int a[n],f[2][n];

int main()

________

int ans=0;

for(int i=1; i<=n; i++)

printf("%d",n-ans);

return 0;

}

將兩岸的友好城市用乙個結構體存起來,以其中乙個城市作為關鍵字進行排序,那麼之後另乙個城市其實會呈最長上公升子串行,例如 \(a\) 岸城市 \(1\)(\(a\)岸城市 \(1\) 的意思是距離河的起點為 \(1\)的 \(a\) 岸城市)和 \(b\) 岸城市 \(3\) 之間如果開通航線,那麼以後的城市都不可能向 \(b\) 岸城市 \(1\)、\(2\)、\(3\) 開通航線。那麼也就呈最長上公升子串行狀,只要套用模板求出最長即可。

注意:一定要排序

**。**:

#includeusing namespace std;

const int n=5005;

struct line

} a[n];

int f[n];

int main()

sort(a+1,a+n+1);

________

int ans=0;

for(int i=1; i<=n; i++)

printf("%d",ans);

return 0;

}

感謝l_z_y對此文章提出的建議,並幫助我寫了 工作安排 這一塊!

本文有彩蛋

演算法(38) 動態規劃(1) 跳躍遊戲 C

題目 給定乙個非負整數陣列,你最初位於陣列的第乙個位置。陣列中的每個元素代表你在該位置可以跳躍的最大長度 步數 判斷你是否能夠到達最後乙個位置。輸入 int arr 輸出 2 題意 不明白的要去搜一下,網上很多說明。思路 當前最優解 下一步的最優解 迭代或者遞迴來完成。這是解決此類問題最簡化的模型之...

動態規劃1(老師的講義,我拷下來的呵呵)

動態規劃的基本模型 在現實生活中,有一類活動的過程,由於它的特殊性,可將過程分成若干個互相聯絡的階段,在它的每一階段都需要作出決策,從而使整個過程達到最好的活動效果。因此各個階段決策的選取不能任意確定,它依賴於當前面臨的狀態,又影響以後的發展。當各個階段決策確定後,就組成乙個決策序列,因而也就確定了...

動態規劃系列專題講義之斐波那契數列

動態規劃系列專題講義 專題一 斐波那契數列 name 動態規劃專題之斐波那契數列 author date 22 03 17 08 56 description 1755 菲波那契數列 描述 斐波那契數列是指這樣的數列 數列的第乙個和第二個數都為1,接下來每個數都等於前面2個數之和。給出乙個正整數a,...