經典題目 聚會的快樂

2021-08-31 01:28:01 字數 3147 閱讀 7523

〖題目〗

聚會的快樂

【問題描述】

你要組織乙個由你公司的人參加的聚會。你希望聚會非常愉快,盡可能地多找些有趣的熱鬧。但勸你不要同時邀請某個人和他的上司,因為這可能帶來爭吵。給定n個人(姓名,他的幽默係數,以及他上司的名字),程式設計找到能是幽默係數和最大的若干個人。

【輸入格式】party.in

第一行乙個整數n(n<100)。接下來每一行描述乙個人的資訊,資訊之間用空格隔開。姓名的長度不超過20的字串,幽默係數是在0到100之間的整數。

【輸出格式】party.out

所邀請的人最大的幽默係數和

【輸入樣例】

bart 10 homer

homer 20 montgomery

montgomery 10 nobody

lisa 30 homer

smithers 40 montgomery

【輸出樣例】

〖分析〗

很遺憾,本來應該1次ac的題目竟然交了2次。看來,讀懂題目還是非常必要的。「失之毫釐,差之千里」啊!

最初的理解,把「勸你不要同時邀請某個人和他的上司」理解成如果乙個人被邀請了,那麼他的上司以及上司的上司等都不能被邀請。但樣例實在太bt了,這樣算出來答案竟然是對的!

然後就興高采烈地提交了。然後wa……

其實這道題目應該也是樹狀dp。不過我還是用記憶化搜尋了——在解決圖的dp問題上,個人更傾向使用記憶化搜尋。先是處理,把人名換成編號——這個用pas實在很累,如果用cpp就爽快多了。這個過程我想不用我詳細解釋了。noip普及組1=的也應該會了(參見下面過程init->cl)。

然後就是dp過程。對於樹狀dp,一般是把森林或者樹轉化為二叉樹,然後進行dp。對於這道題目,構成的圖是乙個森林。只要新建了個結點0,然後這個結點與森林裡的每棵樹的樹根相連。這樣,乙個森林被轉化成一棵樹。接下來是公式:

sum(f(k))            (樹k是樹root的子樹)

f(root)=max

sum(f(kk))+a[root]     (樹kk是樹root的子樹的子樹)

其中,f(root:tree)表示樹root內可以得到的最大的幽默係數和。a[root]表示樹root的根結點的幽默係數。

利用這個公式,把f(root)放入遞迴計算(也可以從葉遞推到根)。最後的答案就是f(root)。

至此,《聚會的快樂》正式解決。

〖程式〗

// task: party

type

people=record

na,nla:string;

ha,la:longint;

end;

varn:longint;

f:text;

a:array [0..100] of people;

procedure init;

vari,j,k,kk:longint;

str:string;

procedure cl;

vari,j,k:longint;

ls:string;

len:longint;

begin

ls:='';

len:=length(str);

i:=1;

while (i<=len)and(str[i]<>' ') do

begin

ls:=ls+str[i];

inc(i);

end;

k:=1;

while (k<=kk)and(a[k].na<>ls) do inc(k);

if k>kk then

begin

inc(kk);

a[kk].na:=ls;

k:=kk;

end;

inc(i);ls:='';

while (i<=len)and(str[i]<>' ') do

begin

ls:=ls+str[i];

inc(i);

end;

val(ls,a[k].ha,j);

inc(i);ls:='';

while (i<=len)and(str[i]<>' ') do

begin

ls:=ls+str[i];

inc(i);

end;

a[k].nla:=ls;

end;

begin

assign(f,'party.in');reset(f);

fillchar(a,sizeof(a),0);

readln(f,n);kk:=0;

for i:=1 to n do

begin

readln(f,str);

cl;end;

for i:=1 to n do

for j:=1 to n do

if a[i].nla=a[j].na then

begin

a[i].la:=j;

break;

end;

a[0].ha:=0;

close(f);

end;

procedure ouot(ans:longint);

vari,j,k:longint;

begin

assign(f,'party.out');rewrite(f);

writeln(f,ans);

close(f);

end;

function calc(dex:longint):longint;

vari,j,k:longint;

c1,c2:longint;

begin

c1:=0;

for i:=1 to n do

if a[i].la=dex then

inc(c1,calc(i));

c2:=a[dex].ha;

for i:=1 to n do

if a[i].la=dex then

for j:=1 to n do

if a[j].la=i then

inc(c2,calc(j));

if c1>c2 then exit(c1)

else exit(c2);

end;

begin

init;

ouot(calc(0));

end.

9935 聚會的快樂

time limit 1 second memory limit 128 mb 問題描述 你要組織乙個由你公司的人參加的聚會。你希望聚會非常愉快,盡可能多地找些有趣的人。但是勸你不要同時邀請某個人和他的上司,因為這可能帶來爭吵。給定n個人 姓名,他幽默的係數,以及他上司的名字 找到能使幽默係數和最大...

LeedCode經典題目

目錄 尋找陣列中心索引 至少是其他數字兩倍的最大數 加一 給定乙個整數型別的陣列 nums,請編寫乙個能夠返回陣列 中心索引 的方法。我們是這樣定義陣列中心索引的 陣列中心索引的左側所有元素相加的和等於右側所有元素相加的和。如果陣列不存在中心索引,那麼我們應該返回 1。如果陣列有多個中心索引,那麼我...

promise經典題目

當乙個promise進入settled狀態時,它後面的then 會被置入微任務佇列。settle的時機,決定了 函式進入微佇列的時間,決定了執行順序。一 new promise resolve then console.log 2 console.log 0 then console.log 3 解...