動態規劃回溯 dp回溯查詢可行解

2021-10-07 22:39:24 字數 3042 閱讀 9443

題目背景

三水非常喜歡吃水果撈,但是每次她都吃不完一整盒果撈,就會吃飽,而吃得太飽會不舒服。

對於果撈裡的每一塊水果,三水都有不同的喜愛程度。她希望在不吃得太飽的基礎上,可以盡可能多地吃掉自己喜歡的水果。你能幫幫她嗎?

題目描述

吃飽的時候三水的飽腹感為w(w

≤10000

)w(w≤10000)

w(w≤10

000)

,超過這個飽腹感三水就會不舒服。在吃果撈之前,三水可能已經吃了一些別的東西,此時她的飽腹感為qqq。

她這次點的水果撈裡有 n

nn 塊水果,對三水來說,第 i

ii 塊水果有 v

iv_i

vi​ 的美味度以及 w

iw_i

wi​ 的飽腹感。

輸入格式

第一行是三個數字:完全吃飽的飽腹感 w

ww ,目前三水的飽腹感 q

qq 和水果塊數 nnn

第二行有n

nn個正整數 w

iw_i

wi​,表示第 i

ii 塊水果的飽腹感

第三行有n

nn個正整數 v

iv_i

vi​,表示第 i

ii 塊水果的美味度

輸出格式

第一行輸出乙個正整數,表示在不吃得太飽的基礎上,三水可能吃掉的最大美味度之和

第二行輸出能吃掉最大美味度的吃法,題目資料保證最優解唯一,輸出最優解時吃掉的水果標號就可以,按照字典序輸出

樣例一輸入

1043

2471

612

輸出

7

12

提示說明

w

≤10000

w≤10000

w≤1000

0,0≤w−

q≤

1000,1

≤n

≤100

0 \le w - q \le 1000,1 \le n \le 100

0≤w−q≤

1000

,1≤n

≤100

題解這個真的是個01揹包。。。

只需要輸出最優解,所以我們用動態規劃回溯的方法。

動態規劃:

用陣列w[i]儲存第i塊水果的飽腹感,陣列v[i]儲存第i塊水果的美味度。

陣列dp[i][j]表示對第i塊水果抉擇,剩餘飽腹程度為j的時候能吃到的最大美味度。而對於每一塊水果都有兩種選擇:吃和不吃

在吃的情況下,吃掉第i塊水果獲得的最大美味度為第i-1塊水果在飽腹感為j-w[i]的情況下獲得的最大美味度。即dp[i][j] = dp[i-1][j-w[i]] + v[i]

不吃的情況下,不吃掉第i塊水果獲得的最大美味度為第i-1塊水果在飽腹感為j時獲得的最大美味度。即dp[i][j] = dp[i-1][j]

對於以上兩種情況,我們取最好結果就可以,即轉移方程:dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]])

空間優化:

我們注意到,對每一塊水果抉擇的情況只與其上一塊水果有關,而與前面所有水果的情況都沒有關係。所以沒有必要用乙個二維陣列去儲存所有水果的情況。我們可以用乙個一維陣列訪問當前水果在各種飽腹感情況下,能獲得的最大美味度。判斷一下如果吃掉當前水果能獲得的美味度比不吃獲得的多,就替換掉,否則不作任何操作。

陣列dp[j]表示剩餘飽腹程度為j的時候能吃到的最大美味度。(一維陣列就地滾動)

則動態轉移方程為:dp[j] = dp[j-w[i]] + v[i]

回溯:可以說是模擬吃水果的過程

使用乙個陣列pre[i][j]來記錄飽腹感為j的時候,要獲得最大美味度應該吃還是不吃第i塊水果,如果吃,就標記為1。否則標記為0。

回溯的過程可以說是乙個模擬吃水果的過程。我們現在可以拿來吃水果的飢餓度為m=w-q,要吃到飢餓度≥0(即飽腹感≤w)的情況。

pre陣列中,從最後一塊水果n開始往前查詢可以吃的水果,如果找到了pre[n][m] == 1,則將水果標號i存入棧中(吃掉),並將m-=w[n],即減去當前已經被吃掉的飽腹感(吃完以後就獲得了這個水果能提供的飽腹感) ,然後繼續檢查下一塊水果n--。直到吃飽或者所有水果都被檢查完一遍為止。

細節:如樣例輸入,要求的是從前往後輸出,即水果的標號按照字典序輸出。但回溯的時候得到的水果標號是從後往前的,所以我們用乙個棧來存一下再輸出。

標程

#include

#include

using namespace std;

const

int n =

105, m =

1005

;int n,dp[m]

, pre[n]

[m];

int w[n]

, v[n]

;int

main()

else

pre[i]

[j]=0;

} cout<

int> s;

while

(m && n)

n--;}

while

(!s.

empty()

)return0;

}

2020 10 01 動態規劃 回溯

框架 初始化 base case dp 0 0 base 進行狀態轉移 for 狀態1 in 狀態1的所有取值 for 狀態2 in 狀態2的所有取值 for dp 狀態1 狀態2 求最值 選擇1,選擇2.509.斐波那契數 var fib function n return cur 322.零錢兌...

01揹包(動態規劃(回溯))

include 所謂動態規劃,就是分治策略加上不同的區域之間相互影響,如何從區域性最優解,到全域性最優解,這便是我們所關注的重點,因為還是分割成一塊一塊的,遞迴入手更好去理解。現有n件物品,其中第i件物品的重量為w i 價值為v i 有一容量為j的揹包,求在不超過揹包容量的情況下,使取得的商品的價值...

LeetCode 自由之路(動態規劃 回溯法)

輸入 ring godding key gd 輸出 4 解釋 對於 key 的第乙個字元 g 已經在正確的位置,我們只需要1步來拼寫這個字元。對於 key 的第二個字元 d 我們需要逆時針旋轉 ring godding 2步使它變成 ddinggo 當然,我們還需要1步進行拼寫。因此最終的輸出是 4...