題意
思路首先,判斷是否有解是十分簡單的。我們只需要看在給每個小頭分配1個,大頭分配k個的情況下,所需要的果子的數量是否大於了蘋果的總數。也就是m+k是否》n。
接下來就是有解的情況了。
首先我們需要知道,再分配好大頭之後,剩下的果子必然存在一種分配方式,使得九頭龍的難受值不會再增加。我們可以先考慮一堆連續的有連邊的果子,我們為了減小難受值,應該盡量分配不同的頭來吃。由於所有的小頭需求的果子數量是沒有限制的,那麼我們就可以極限地想,在這一堆果子中分配完全不同的小頭來吃;若這一堆裡邊的果子數量大於了小頭數,那麼又可以迴圈地進行類似的操作。
解決了這個問題之後,我們就只需要考慮大頭了。對於每乙個果子來說,它要麼是被大頭吃,要麼是不被。於是,我們便可以用樹形dp來解決:
我們定義狀態:
dp[u][sum][0]表示以u為根節點,它以及它的兒子中,大頭吃了sum個果子,並且當前這個沒有被大頭吃。那麼我們就可以利用樹上揹包來進行k的分配從而求得最優解了。那麼dp[u][sum][1]就是表示以u為根節點,它以及它的兒子中,大頭吃了sum個果子,並且當前這個被大頭吃了。
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個果子中理所當然地應該包括唯一的乙個最大的果子。果...