樹形結構計數問題 記憶化搜尋

2021-10-10 01:21:00 字數 1803 閱讀 2720

分析:這裡要求的是全部節點的距離和,可以定義子問題為:某乙個節點去掉它的某一條邊而形成的子樹中,該節點的距離和以及該子樹的節點數.只需要知道全部節點的該資訊,對每個節點就可以通過其臨界節點的該資訊得到這個節點的距離和.總的時間代價是o(2

∗∣n−

1∣)o(2*|n-1|)

o(2∗∣n

−1∣)

的.相比於o(∣

n∣2)

o(|n|^2)

o(∣n∣2

)的複雜度是有優化的.

**:

class

solution

; sub_tree_info st_infos =;}

;public

: vector<

int>

sumofdistancesintree

(int n, vector

int>>

&edges)

}return result;

}/**

* 生成整個節點陣列

* @param num: 節點個數

* @param e:邊表

*/public

:void

generate_nodes

(int num, edge &e)

}/**

* 計算某個節點切掉它的一條邊,而形成的子樹的資訊(子樹代價和,子樹節點數)

* @param sub_tree_root:該節點的代號(這個節點作為子樹的根節點)

* @param node_cutted:形成子樹的過程中需要切割的節點

* @return 乙個info型別,info::first是子樹代價和,info::second是子樹節點數

*/public

: info calculate_sub_tree

(int sub_tree_root,

int node_cutted)

// 記錄中存在該子樹記錄:

sub_tree_info::iterator it = rnode.st_infos.

find

(node_cutted);if

(it != rnode.st_infos.

end())

// 記錄中不存在該子樹的記錄:

int st_cost =0;

int st_count =1;

for(

int i =

0; i < rnode.edge_number; i++)}

// 記錄得到後將其儲存:(寫了一堆std::move,有必要嗎? 能更簡潔嗎?)

rnode.st_infos.

insert

( std::

move

( pair<

int, info>

( node_cutted,

std::

move

(info

(st_cost, st_count)))

));// 返回記錄:

return std::

move

(info

(st_cost, st_count));

}private

: vector

*nodes;

};

C Garland (樹形DP 子樹計數問題)

又攻克一道樹形dp題,首先子樹計數問題,感覺都是先自下而上跑一遍dfs,然後根據題意然後抉擇得套路。一顆有根樹,分成三棵子樹,保證點權和相互相等。分析 子樹滿足ans 3,並且ans 3 0加入就可以了,滿足兩個點或者以上,就是行 為啥說2以上 這裡就是我得wa得點,可以所有得點值為0,你就知道了 ...

序列計數(記憶化搜尋)(C )

問題描述 小明想知道,滿足以下條件的正整數序列的數量 第一項為 n 第二項不超過 n 從第三項開始,每一項小於前兩項的差的絕對值。請計算,對於給定的 n,有多少種滿足條件的序列。輸入格式 輸入一行包含乙個整數 n。輸出格式 輸出乙個整數,表示答案。答案可能很大,請輸出答案除以10000的餘數。樣例輸...

硬幣問題 記憶化搜尋與遞推的轉換

一 問題描述 有n種硬幣,面值分別為v1,v2,v3,vn,每種都有無限多。給定非負整數s,可以選用多少硬幣,使得面值之和恰好為s?輸出硬幣數目的最小值和最大值。1 n 100,0 s 10000,1 vi s.二 解題思路 將每種面值看作乙個點,表示 還需湊足的面值 則初始狀態為s,目標狀態為0。...