昨天本來就能寫的,結果寫了倆個題寫了四五個小時,於是乎拖到今天了。
這個題就很好寫了,不像狀態壓縮,真的是難理解…大佬部落格
f[u][0]表示從以u為根節點,不選u的方案。
f[u][1]表示從以u為根節點,選u的方案。
所以f[u][0] = ∑max(f[si][0],f[si][1])i是遍歷下一層的子節點
f[u][0] = ∑f[si][0] i是遍歷下一層的子節點
#include
using
namespace std;
const
int n=
6010;;
int f[n][2
];int h[n]
,e[n]
,ne[n]
,idx;
bool st[n]
;int n;
vector<
int> ve[n]
;void
dfs(
int u)
}int
main()
int root=1;
while
(st[root]
) root++
;//求取根節點
dfs(root)
; cout<<
max(f[root][0
],f[root][1
])
}
其實更下面喜歡這樣寫…感覺舒服多了…
如果是線型的一串一維陣列的話 不能選擇相鄰的數字 要讓選擇的數的和最大
那麼就有遞推方程dp[i] = max(dp[i-1],dp[i-2] + a[i])
max裡面前乙個式子代表我不選a[i] 那麼就能從dp[i-1] 轉移過來
後面乙個代表我選了這個 那麼就是從dp[i-2] + a[i] 轉移過來
兩者取最大值就是我們需要的答案 那麼這題的話就可以用這個思想
如果我們選擇了這個節點的值的話 我們就只能從這個節點出發的下下一層轉移了 下一層不能選了
如果我們不選這個節點 我們直接從下一層節點轉移就好了 兩者取最大值 附:大佬部落格
#include
using
namespace std;
const
int maxn =
6010
;int val[maxn]
, in[maxn]
;int dp[maxn]=;
// 記憶化優化 相當於剪枝了
vector<
int> g[maxn]
;// 記錄樹
intdfs
(int root)
ans1 +
=dfs
(g[root]
[i])
;// 我不選這個就可以直接從這一層轉移
tans =
max(ans1,ans)
;// 兩者取一下最大值
}return dp[root]
= tans;
// 記憶化 避免很多的多餘運算
}int
main()
int u,v;
while
(cin>>u>>v&&u!=0)
int root , ans =0;
for(
int i =
1; i <= n; i++
) ans =
dfs(root)
; cout<}
怎麼說呢,這幾天寫dp寫的真的是心累,智商低的人的苦你們是不會理解的…未來三天寫不寫dp了,準備惡補數學知識三天. 動態規劃 樹形DP
樹形dp,即在樹上進行的動態規劃,由於樹固有的遞迴性質,因此樹形dp往往也遞迴進行。某大學有 n nn 個職員,編號為 1.n1.n 1.n 他們之間有從屬關係,也就是說他們的關係就像一棵以校長為根的樹,父結點就是子結點的直接上司。現在有個周年慶宴會,宴會每邀請來乙個職員都會增加一定的快樂指數 r ...
( 動態規劃專題 ) 樹形dp
動態規劃專題 樹形dp 直接看例題 p2015 二叉蘋果樹 有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3...
動態規劃二(樹形DP)
顧名思義,是指將dp建立在樹狀結構的基礎上。問題描述 有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?輸入格式 第一行包含乙個整數 n 接下來的一行包含 n 個正整數,第 i 個正整數代表點 i 的權值。接...