本文共 3768 字,大约阅读时间需要 12 分钟。
树形动态规划的框架可以这样写:
Proceduredfs(v);
var i:longint;
Begin
vis[v]:=ture;
for i:=1 to n do
if father[i]=v then// 一般树形动态规划的操作是从叶子节点向根节点推导,所以必须要确定i时v的孩子
begin
if not vis[i]then dfs(i);//如果孩子节点i已经被计算过就不需要再次计算,这里就体现了动态规划的思想
dp[v] fun(dp[i])//这里的分支递归又体现了树的递归操作思想
end;
End;
0 0
input | output |
---|---|
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0 | 5 |
a[i].in=∑a[i.son].out
a[i].out=∑max{a[i.son].in, a[i.son].out}
in 表示q请 i ,out 表示b不请 i 。
下面说下左儿子右兄弟x新节点的c插入方法:
1。这是一棵二叉树(不大相就是)
2。先帮他认好父亲和兄弟
3。让他爸认识他,并遗弃他的二哥 (为逃过罚款,户口上只能有一个儿子)
#includeusing namespace std;struct node { int boss,son,brother; int in,out; void init() { boss = brother = son = in = out = 0 ; } int max() { return in > out ? in : out ; }} a[6002];void treedp(int father){ int son = a[father].son; while (son) { treedp(son); a[father].in+=a[son].out; a[father].out+=a[son].max(); son=a[son].brother; } }int main(){ int i,l,k,n; while(cin >> n){ for (i=1; i<=n; i++) { a[i].init(); cin >> a[i].in; } while (cin >>l >>k && l+k) { //边读入建二叉树 a[l].boss = k; a[l].brother = a[k].son; a[k].son = l; } for (i=1;i<=n;i++) if (a[i].boss==0) { treedp(i); cout << a[i].max() << endl; break; }}}
也可以不转换二叉树
#include#include #include using namespace std;const int MAXN=6003;int a[MAXN];int father[MAXN];int f[MAXN][2];int n;void TreeDP(int i){ f[i][1]=a[i]; for(int j=1;j<=n;j++) { if(father[j]==i) { TreeDP(j); f[i][0]+=max(f[j][0],f[j][1]); f[i][1]+=f[j][0]; } }}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",a+i); } int x,s; memset(father,0,sizeof(father)); memset(f,0,sizeof(f)); while(scanf("%d %d",&x,&s),x&&s) { father[x]=s; } for(int i=1;i<=n;i++) { if(father[i]==0) { TreeDP(i); printf("%d\n",max(f[i][0],f[i][1])); break; } } return 0;}
转载地址:http://oseti.baihongyu.com/