樹形DP 貪吃的九頭龍

2021-08-17 03:17:40 字數 1883 閱讀 3211

題意

思路首先,判斷是否有解是十分簡單的。我們只需要看在給每個小頭分配1個,大頭分配k個的情況下,所需要的果子的數量是否大於了蘋果的總數。也就是m+k是否》n。

接下來就是有解的情況了。

首先我們需要知道,再分配好大頭之後,剩下的果子必然存在一種分配方式,使得九頭龍的難受值不會再增加。我們可以先考慮一堆連續的有連邊的果子,我們為了減小難受值,應該盡量分配不同的頭來吃。由於所有的小頭需求的果子數量是沒有限制的,那麼我們就可以極限地想,在這一堆果子中分配完全不同的小頭來吃;若這一堆裡邊的果子數量大於了小頭數,那麼又可以迴圈地進行類似的操作。

解決了這個問題之後,我們就只需要考慮大頭了。對於每乙個果子來說,它要麼是被大頭吃,要麼是不被。於是,我們便可以用樹形dp來解決:

我們定義狀態:

dp[u][sum][0]表示以u為根節點,它以及它的兒子中,大頭吃了sum個果子,並且當前這個沒有被大頭吃。

那麼dp[u][sum][1]就是表示以u為根節點,它以及它的兒子中,大頭吃了sum個果子,並且當前這個被大頭吃了。

那麼我們就可以利用樹上揹包來進行k的分配從而求得最優解了。

dp[u][sum][0]=sigma sigma=sum;

dp[u][sum][1]=sigma sigma=sum-1;

這裡要注意的是,如果m==2,那麼之前我們定義的那一堆果子中就只能放同一種果子,這就意味著之前的結論已經不成立了,也就是給小頭分配果子也需要增加難受值。dp式也要發生變化:

dp[u][sum][0]=sigma sigma=sum;

dp[u][sum][1]=sigma sigma=sum-1;

最終狀態也就是dp[1][k][1].

**

#include

#include

#include

#include

#define maxn 300

#define inf 0x3fffffff

using

namespace

std;

struct edge

edge(int _len,int _to):len(_len),to(_to){}

};struct point

poi[maxn+5];

vector

g[maxn+5];

int dp[maxn+5][maxn+5][2];

int n,m,k;

void dfs1(int u,int fa)

dp[u][sum][0]=ret;

ret=inf;

for(int j=0;j<=sum;j++)

dp[u][sum][1]=ret;}}

}}void dfs2(int u,int fa)

dp[u][sum][0]=ret;

ret=inf;

for(int j=0;j<=sum;j++)

dp[u][sum][1]=ret;}}

}}void transform()

int main()

if(m+k>n)//無法滿足

transform();

if(m==1)//全部給大頭

if(m==2)//只有兩個頭(乙個小頭)

dfs1(1,-1);

else

//有多個頭

dfs2(1,-1);

printf("%d\n",dp[1][k][1]);//末狀態

return

0;}

如有不明之處,敬請提出!!!

貪吃的九頭龍

傳說中的九頭龍是一種特別貪吃的動物。雖然名字叫 九頭龍 但這只是說它出生的時候有九個 頭,而在成長的過程中,它有時會長出很多的新頭,頭的總數會遠大於九,當然也會有舊頭因衰老而自己脫落。有一天,有 m 個腦袋的九頭龍看到一棵長有 n個果子的果樹,喜出望外,恨不得一口把它全部吃掉。可是必須照顧到每個頭,...

貪吃的九頭龍

時間限制 2 sec 記憶體限制 128 mb 提交 57 解決 22 提交 狀態 我的提交 傳說中的九頭龍是一種特別貪吃的動物。雖然名字叫 九頭龍 但這只是說它出生的時候有九個頭,而在成長的過程中,它有時會長出很多的新頭,頭的總數會遠大於九,當然也會有舊頭因衰老而自己脫落。有一天,有m 個腦袋的九...

貪吃的九頭龍

題目描述 有一天,有m個腦袋的九頭龍看到一棵長有n個果子的果樹,想把果子一口全部吃掉。可是必須照顧到每個頭,因此它需要把n個果子分成m組,每組至少有乙個果子,讓每個頭吃一組。這m個腦袋中有乙個最大,稱為 大頭 是眾頭之首,它要吃掉恰好k個果子,而且k個果子中理所當然地應該包括唯一的乙個最大的果子。果...