題目背景
三水非常喜歡吃水果撈,但是每次她都吃不完一整盒果撈,就會吃飽,而吃得太飽會不舒服。
對於果撈裡的每一塊水果,三水都有不同的喜愛程度。她希望在不吃得太飽的基礎上,可以盡可能多地吃掉自己喜歡的水果。你能幫幫她嗎?
題目描述
吃飽的時候三水的飽腹感為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...