POJ 1694 古老的遊戲

2021-07-24 03:37:26 字數 2539 閱讀 1620

【問題描述】

有乙個古老的石頭遊戲,該遊戲基於任意一棵樹t,遊戲的目標是在樹t的根節點上放一顆石頭,遊戲的規則如下:

1、 遊戲開始前,玩家先將k個石頭放入桶中。

2、 在遊戲的每一步,玩家從桶中拿一顆石頭放到樹的乙個空的葉子節點上。

3、 當乙個節點p的所有r個子節點都有乙個石頭,則移去r個子節點上的石頭,然後將乙個石頭放到節點p上。剩下的r-1個石頭重新放到桶中重複使用。

如果玩家根據以上規則放置石頭,並最終在根節點上放置一顆石頭,則贏得遊戲。

現在的任務是求出遊戲開始時,石頭數k的最小值,使得玩家能在給定樹的情況下贏得遊戲。

【輸入格式】

第一行輸入測試用例的個數t,每個測試用例是一顆樹的描述。第二行開始輸入每棵樹的描述。

每棵樹有n個節點,節點標號為1,2,…n,每個節點可以有任意個子節點,根節點標號為1,。樹的描述第一行為節點數n,第二行開始按照節點標號順序描述n個節點的子節點,每行第乙個數為標號p,第二個數為子節點數r,如果r不為0,接下來為r個子節點的標號。

【輸出格式】

對每棵樹,輸出石頭數的最小值。

【輸入樣例】

2 7

1 2 2 3

2 2 5 4

3 2 6 7

4 0

5 0

6 0

7 0

12 1 3 2 3 4

2 0

3 2 5 6

4 3 7 8 9

5 3 10 11 12

6 0

7 0

8 0

9 0

10 0

11 0

12 0

【輸出樣例】

3 4

【資料範圍】

1<=t<=10 n<200

題意:

給出一棵一般的樹,按如下的三種規則在樹上放石子:

1,在遊戲開始時,玩家可以拿k個石子放在水桶裡。

2,在遊戲的每一步,玩家可以從水桶裡拿出乙個石子,並放在任意乙個空的葉子上。

3,當乙個父節點的r個子節點都被放上了乙個石子,可以將這r個石子都拿去並在父節點上放乙個石子。水桶裡石子可以再次使用。

顯然,最終根上會被放上乙個石子,問的是,求用最少的石子達到上述要求,求這個最小值。(有很多k,求最小的那個);

思路: 設所求結果用result來表示,我們要求的是以1為根的result,這個結果必定依賴於它的子節點的相關資訊。這個資訊會是什麼呢?

考慮一棵樹的子孫是該樹的子樹。假設1的子孫分別為r1,r2,r3。那麼r1,r2,r3,都是1的子樹的根。假設以r1,r2,r3為根的上述結果分別為result1,result2,result3,顯然它們之和一定能達到1上也能被放上石子的目的。那這個值是不是最小的呢?假設result1>=result2>=result3,我們用result1個石子讓r1上放上了乙個石子,此時我們剩餘了result1-1個石子沒有用,這些石子可以彌補result2,最終可能會得到乙個更小的值(<=result1+result2+result3,通過對先前石子的重複利用)。如何安排這種彌補方式呢?

最大值優先。r1需要的石子result1最大,那麼最終的結果必定result>=result1,然而最終只需在r1上放乙個石子,留下了result1-1個石子。

那麼r1 ,r2一共需要result = result1+result2-min( result-1,result2 )個石子,其中min(result1-1,result2)被加了兩次,所以要減掉一次。

這樣r1,r2就合併成了乙個節點,最少需要result個石子,那麼result=result+result3-min(result-2,result3)。最終得解。

顯然這是乙個貪心演算法,符合貪心選擇和最優子結構

#include

#include

#include

#include

#include

#include

#define mod 10007

#define maxn 505

#define oo 100000000

using

namespace

std;

int n,t;

int sz[maxn],d[maxn],g[maxn][maxn];

void read(int &x)

if(ok) x=-x;

}void dfs(int i)

int cnt=0,a[300];

for(int k=1;k<=sz[i];k++)

sort(a+1,a+cnt+1);

int num=a[cnt]-1,sum=a[cnt];

for(int k=cnt-1;k>=1;k--)

if(a[k]>num) sum+=(a[k]-num);

d[i]=sum;

}void task()

void in()

task();

}}int main()

回文回文數 HUST 1694

problem 如果乙個數從左往右讀和從右往左讀都是一樣,那麼這個數就叫做 回文數 事實上,有一些數 如 21 在十進位制時不是回文數,但在其它進製 如二進位制時為 10101 時就是回文數。現在,你需要找出來,前 n 個滿足大於 s 且在兩種或兩種以上進製 二進位制至十進位制 上是回文數的十進位制...

POJ 1753 POJ 2965 解題報告

poj 1753 poj 2965 解題報告 poj 1753 和 poj 2965 是同一型別的題目,但是2965 有乙個比較簡單的方法來解決。poj 1753 我用的是打表的方法,打表很不厚道。思路 首先我們需要確定儲存的資料結構,從網上搜得用二進位制位來存,這確實是個很巧妙的方法,例如,我們將...

poj 3074 poj 3076(精確覆蓋)

兩個題都是數獨,題意很明確。建圖的思路大神寫的很好 行 一共9 9 9 729行。一共9 9小格,每一格有9種可能性 1 9 每一種可能都對應著一行。列 一共 9 9 9 9 81 324 種前面三個9分別代表著9行9列和9小 塊。乘以9的意思是9種可能,因為每種可能只可以選擇乙個。81代表著81個...