洛谷 P1417烹調方案

2022-02-06 05:09:01 字數 2982 閱讀 8001

一共有n件食材,每件食材有三個屬性,ai,bi和ci,如果在t時刻完成第i樣食材則得到ai-t*bi的美味指數,用第i件食材做飯要花去ci的時間。

求最大美味指數之和。

顯然的0/1揹包,但是,它與平常的0/1揹包不同之處在於:平常的物品不會因為時間的延續而使價值貶值,也就是說,先放a、先放b是無所謂的。

但是這個題,「ai-t*bi」的判斷方法,顯然相同物品的不同放置順序,都可能得到不同的答案。

所以必然要排序。

但是怎麼排序?

按照ci排?但是不一定時間短的要先做,可能其它食物b太大,貶值的很厲害。

按照bi排?但是先做貶值快的,可能由於做的時間長,仍然可能造成其它剩餘食物貶值總和更大。

按照(sumb-bi)*ci排?但是由於不一定做i的時候,其它的所有的食物都留下等著做,損失其實不一定有sumb-bi那麼大

按照ai-(sumb-bi)*ci排?但是這其實是只考慮了第乙個做誰,仍然可能不是最優子結構。

我們這樣考慮:

設身處地地想一想,我們假設已經過了p時間,還剩下兩個食材x,y,你會怎麼辦?

一定會考慮,先做x或者先做y哪個會最大收益。

先做x:

a[x]-(p+c[x])*b[x]+a[y]-(p+c[x]+c[y])*b[y] —— ①

先做y:

a[y]-(p+c[y])*b[y]+a[x]-(p+c[y]+c[x])*b[x] —— ②

對這兩個式子化簡,得到①>②的條件是c[x]*b[y]所以,對於有若干個食物,道理同樣如此。

我們先按這個標準排一下序,然後0/1揹包即可。

這裡,我定義f[i][j]為,前i個物品,最後一次做完飯是在j時刻。也可以省略第一維。

(至於為什麼要排序,假設現在x優於y,如果我們先迴圈的是x,就代表會先做x,再做y的時候,可以從上一次做完x的時刻轉移過來美味程度。

如果y在了前面迴圈,那麼想要同時做x,y,x必須從上一次的某乙個y處轉移過來,那麼這個時候,x一定不是第乙個做的。

或者,就算是x想要第乙個做,但是y已經迴圈過去了,不會再從x做完後的時間轉移到更靠後的j,也就扔掉了正解的轉移路徑。)

**:

#include#define ll long long

using

namespace

std;

const

int n=55

;const

int t=100000+10

;ll f[t];

intsb;

intn,t;

struct

node

}foo[n];

intmain()

ll ans=0

;

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

ans=max(ans,f[i]);

cout

}

再過t天就是kate的生日了,coffee打算送它一些蛋糕。在coffee和kate的世界,蛋糕是做不出來的,而是種出來了。

coffee收藏著n個蛋糕種子。第i個蛋糕種子需要在室內培育連續pi天才能長成幼苗,之後將它移栽到室外,再經過qi天後就會結出乙個美味度為ri的蛋糕。移栽蛋糕苗、為室外的蛋糕澆水以及收取成熟的蛋糕花費的時間對於coffee來說可以忽略不計,但由於長成幼苗前的蛋糕比較嬌嫩,照顧起來也更麻煩,coffee每天最多隻會照顧一棵蛋糕幼苗。

更具體地,如果coffee在第t0天開始室內培育第i個蛋糕種子,那麼它的室內培育工作會占用coffee第t0..t0+(pi)-1,並會在t0+pi+(qi)-1天結出蛋糕。在t0..t0+(pi)-1天,coffee不會開始或同時培養其他種子。

coffee希望在kate生日時,送給kate的蛋糕們的美味度總和盡量大。也就是說,在接下來的t天內,kate最多能收穫蛋糕的美味度總和最大是多少?注意,即使乙個蛋糕苗在第t天前已經被移出了室外,只要它在kate的生日前沒能結出蛋糕,它的美味度就不會被計算到總美味度中。

發現q這個延時很麻煩,處理的時候還得想之前有沒有種過。可以取巧地,假設過完了p天,就立刻熟了,收穫了,但是「收穫」的這一天不能晚於t-qi(這個轉化就是合法的)

所以就剩乙個0/1揹包了。

因為對於不同的物品,有不同的揹包上界,既然如此,肯定先考慮,把上界低的先放進包裡,因為再高了就放不了了。

上界高的,能力大,就可以放到再靠上的包的空間裡。

也就是把公共的區間讓範圍小的先去填充。排序即可。

#include#include

#include

#include

using

namespace

std;

const

int n=300+10

;const

int t=20000+10

;int

f[n][t];

struct

nodeca[n];

intn,t;

bool

cmp(node a,node b)

intmain()

for(int j=1;j<=t;j++)

cout

cout

<}

int ans=0

;

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

ans=max(ans,f[n][i]);

printf("%d

",ans);

return0;

}

1.揹包的變式其實是非常多的,總體的定義、迴圈相差不大,但是關鍵點多出在排序。

2.排序本質上都是兩兩之間的物品進行最優解的比較,所以考慮如何排序的時候,可以嘗試單獨考慮這兩個元素之間的大小關係,從而列出式子。

3.揹包不能憑感覺瞎想,一定要分析好物品迴圈的先後順序。

4.揹包本質上還是揹包,就是往有限空間裡放東西,只是東西千奇百怪罷了,但是考慮方式是可以轉化到基礎的放東西模型上的。

5.揹包物品的迴圈順序,本質上就是考慮放物品的先後順序。不會存在先考慮,卻在實際操作中是後放進去的。

洛谷P1417 烹調方案

由於你的幫助,火星只遭受了最小的損失。但gw懶得重建家園了,就造了一艘飛船飛向遙遠的earth星。不過飛船飛到一半,gw發現了乙個很嚴重的問題 肚子餓了 gw還是會做飯的,於是拿出了儲藏的食物準備填飽肚子。gw希望能在t時間內做出最美味的食物,但是這些食物美味程度的計算方式比較奇葩,於是絕望的gw只...

洛谷P1417 烹調方案

這道題不同於普通的01揹包,不同的先選擇的做菜策略會對之後產生不同的影響,即不滿足 無後效性 但是,考慮一種選擇策略,假設有兩個先後做的菜i和j,交換他們的順序會產生什麼影響呢?假設ij之前的時間為t 先i後j a i t c i b i a j t c i c j b j 先j後i a j t c...

洛谷 P1417烹調方案

洛谷 p1417烹調方案 由於你的幫助,火星只遭受了最小的損失。但gw懶得重建家園了,就造了一艘飛船飛向遙遠的earth星。不過飛船飛到一半,gw發現了乙個很嚴重的問題 肚子餓了 gw還是會做飯的,於是拿出了儲藏的食物準備填飽肚子。gw希望能在t時間內做出最美味的食物,但是這些食物美味程度的計算方式...