〖題目〗
聚會的快樂
【問題描述】
你要組織乙個由你公司的人參加的聚會。你希望聚會非常愉快,盡可能地多找些有趣的熱鬧。但勸你不要同時邀請某個人和他的上司,因為這可能帶來爭吵。給定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 解...