藍橋杯刷題心得 動態規劃

2021-10-22 18:35:07 字數 3996 閱讀 1961

這裡單獨寫一下動態規劃專題,藍橋杯當中一定會出一道動態規劃的題目所以稍微彙總一下。

(源於藍橋杯2020屆一道題目)

1.某市市長獲得了若干批口罩,每一批口罩的數目如下:(如果你把以下文字複製到文字檔案中,請務必檢查複製的內容是否與文件中的一致。在試題目錄下有乙個檔案 mask.txt,內容與下面的文字相同)

9090400,8499400,5926800,8547000,4958200,4422600,5751200,4175600,6309600

,5865200,6604400,4635000,10663400,8087200,4554000

現在市長要把口罩分配給市內的 2 所醫院。由於物流限制,每一批口罩只能全部分配給其中一家醫院。市長希望2 所醫院獲得的口罩總數之差越小越好。請你計算這個差最小是多少?

首先求最值那麼一般思路都是往dp方向上去靠,同時這道題又是最經典動態規劃中的揹包問題,首先先要判斷數是否可重用,不可重用就是子集揹包問題,可重用就是完全揹包問題,這兩者之間有微妙的差別

藍橋杯演算法模板常用套路

ps:就是這其中內層迴圈的差別,該題題解如下,j應該是從後往前反向遍歷,因為每個物品(或者說數字)只能用一次,以免之前的結果影響其他的結果。最值問題一般是(dp動態規劃,那麼這道題是一道變形的揹包問題)

對於揹包容量為sum/2的有i批個口罩,口罩數為nums[i],那麼最大差值是多少

static

int[

] dp =

newint

[98090000];

static

int sum =0;

static

int[

] nums =

;public

static

void

main

(string[

] args)

system.out.

println

(sum)

;int v = sum /2;

for(

int i =

1; i < nums.length; i++)}

system.out.

println

(dp[v]);

system.out.

println

(sum - dp[v]*2

);}

2.再來看一道題目,輸入乙個只包含正整數的非空陣列nums,請你寫乙個演算法,判斷這個陣列是否可以背分割成兩個子串,使得兩個子集的元素和相等。

輸入nums[1,5,11,5],演算法返回true,因為nums可以分割成[1,5,5]和[11]

輸入nums[1,3,2,5],演算法返回false,因為nums無論如何都不能分割成兩個和相等的子集

可以把問題轉換成揹包問題,對於容量為sum/2的揹包和i個物品,其他重量為nums[i],是否存在一種裝法,恰好將揹包裝滿,能轉化為揹包問題就直接套用模板

static

int sum =0;

static

int[

] nums =

;static

boolean

dp =

newboolean[22

];public

static

void

main

(string[

] args)

public

static

boolean

canpartition

(int

nums)

if(sum %2!=

0)return

false

;int v = sum /2;

for(

int i =

1; i < nums.length; i++)}

return dp[v]

;}

3.那麼接下來我們看一道完全揹包問題,零錢兌換,給定不同面額的硬幣coins和乙個總金額amount,寫乙個函式來計算可以湊成總金額的硬幣組合數。假設每一種面額的硬幣有無限個。

比如輸入amount = 5,coins = [1,2,5],演算法應該返回4,因為有如下四種方式可以湊出目標金額:

5 = 5

5 = 2 + 2 + 1

5 = 2 + 1 + 1 + 1

5 = 1 + 1 + 1 + 1 + 1

我們可以把這個問題轉換成揹包問題,對於揹包容量為5的揹包有i個硬幣,硬幣的大小為coins[i],數量為無限個。(無限個意味著可以重複使用硬幣,參照揹包問題和完全揹包的套路模板,其實區別就是在此是否可重用),對於內層迴圈就是揹包容量進行迴圈,前者是從z後往前(防止重複使用影響節後),後者是從前往後迴圈

public

class

bagdemo1test

; system.out.

println

(moneychange

(amount, coins));

}public

static

intmoneychange

(int amount,

int[

] coins)

}return dp[amount];}

}

來做三道連續的dp陣列題目來鞏固一下動態規劃

4.leetcode打家劫舍題目1

ps:這道題要求求最值,首先先找狀態和選擇,狀態很明顯就是可選擇的房屋,那麼選擇就是選擇該房子或者不選擇該房子,根據套路模板

for

(狀態1 in 狀態1 的所有取值)

for(狀態2 in 狀態2 的所有取值)

dp[i]

= 計算(選擇1,選擇2

)//關鍵就是在於對dp陣列的定義並且這個計算,指的是要對於題目而言dp陣列的定義來進行計算

那麼可以觀察該題目,因為題目的dp[i]只與dp[i + 1]和dp[i + 2]的值有關,所以可以將空間複雜度降為o(1),如下所示.

public

class

demo2

return dp_i;

}}

5.leetcode打家劫舍2

這道題和上一題類似,但是房屋是環形的,其實可以就只有三種情況

1.要麼第乙個和最後乙個都不取

2.第乙個取,最後乙個不取

3.最後乙個取,第乙個不取

後兩者已經將第一種情況涵括,將後兩者的情況進行求最值即可。

public

class

demo3

/* * 其實和上一道題差不多,就是要對引數進行更改就行

* */

public

introbrange

(int

nums,

int end,

int start)

return dp_i;

}}

6.leetcode打家劫舍3

那麼這道題涵蓋遞迴和動態規劃,首先樹形結構一定要考慮遞迴,並且對於遞迴樹,一定要對其進行剪枝,用乙個hashmapmemo備忘錄取存放值,如果備忘錄中存在值就可以取出。

public

class

demo4

}

總結:那麼我們來**一下動態規劃回溯演算法之間的關係

先說一下回溯演算法,dfs和回溯演算法對於這兩者而言,我個人也是模稜兩可,而對於套路模板中,我所發現的動態規劃和dfs之間有相似之處就是,有時候要區別對數字是否可重用有一些相應的操作。

藍橋杯刷題

題目 問題描述 給定圓的半徑r,求圓的面積。輸入格式 輸入包含乙個整數r,表示圓的半徑。輸出格式 輸出一行,包含乙個實數,四捨五入保留小數點後7位,表示圓的面積。說明 在本題中,輸入是乙個整數,但是輸出是乙個實數。對於實數輸出的問題,請一定看清楚實數輸出的要求,比如本題中要求保留小數點後7位,則你的...

藍橋杯刷題

題目 問題描述 求1 2 3 n的值。輸入格式 輸入包括乙個整數n。輸出格式 輸出一行,包括乙個整數,表示1 2 3 n的值。樣例輸入 4樣例輸出 10樣例輸入 100說明 有一些試題會給出多組樣例輸入輸出以幫助你更好的做題。一般在提交之前所有這些樣例都需要測試通過才行,但這不代表這幾組樣例資料都正...

藍橋杯刷題

題目 問題描述 給定n個十六進製制正整數,輸出它們對應的八進位制數。輸入格式 輸入的第一行為乙個正整數n 1 n 10 接下來n行,每行乙個由09 大寫字母af組成的字串,表示要轉換的十六進製制正整數,每個十六進製制數長度不超過100000。輸出格式 輸出n行,每行為輸入對應的八進位制正整數。注意 ...