zoukankan      html  css  js  c++  java
  • 树形DP 题目库

      树形DP,是一个很好理解的DP,树形结构很容易理解DP的!

      在存储结构上,学习了左孩子,右兄弟的结构:

    定义代码:

    定义代码
    struct node{
    int val;
    int father;
    int child;
    int brother;
    void init()
    {
    father
    = child = brother = -1;
    val
    = 0;
    }
    }tree[maxn];

    添加边:

    void AddEdge(int a,int b,int c)
    {
    tree[b].father
    = a;
    tree[b].brother
    = tree[a].child;
    tree[a].child
    = b;
    tree[b].val
    = c;//把边的值赋给了某点
    }

    hdu 1520   Anniversary party

    http://acm.hdu.edu.cn/showproblem.php?pid=1520

    简单树形DP,做的第一个DP。

    代码
    /*简单树形DP题,比较好的地方是用到了左孩子,右兄弟的森林存储结构*/

    #include
    <iostream>
    using namespace std;
    const long maxn = 6005;
    #define max(a,b) (a>b?a:b)
    int n;

    struct node
    {
    int Take;
    int Not;
    int father;
    int child;
    int brother;
    void init()
    {
    father
    = child = brother = -1;
    Take
    = 0;
    Not
    = 0;
    }
    int Max()
    {
    return Take>Not?Take:Not;
    }
    }tree[maxn];

    void Init()
    {
    int i,l,k;

    for(i=1;i<=n;i++)
    {
    tree[i].init();

    scanf(
    "%d",&tree[i].Take);
    }
    while(scanf("%d%d",&l,&k)!=EOF && (l!=0 || k!=0))
    {
    tree[l].father
    = k;
    tree[l].brother
    = tree[k].child;
    tree[k].child
    = l;
    }

    //把森林合成一棵树
    int pre = -1;
    for(i=1;i<=n;i++)
    {
    if(tree[i].father == -1)
    {
    tree[i].father
    = 0;
    tree[i].brother
    = pre;
    tree[
    0].child = i;
    pre
    = i;
    }
    }
    tree[
    0].father = -1;
    tree[
    0].brother = -1;
    tree[
    0].Take = 0;
    tree[
    0].Not = 0;
    }

    void Sum(int dir)
    {
    int c = tree[dir].child;
    while(c != -1)
    {
    Sum(c);
    tree[dir].Take
    += tree[c].Not;
    tree[dir].Not
    += tree[c].Max();
    c
    = tree[c].brother;
    }
    }

    void print()
    {
    int num = tree[0].Max();
    printf(
    "%d\n",num);
    }

    int main()
    {
    while(scanf("%d",&n)!=EOF)
    {
    Init();
    Sum(
    0);
    print();
    }
    return 0;
    }

    hdu 3660 Alice and Bob's Trip

    http://acm.hdu.edu.cn/showproblem.php?pid=3660

    Bob选最大子结点走,Alice选最小子结点走!

    但因为要符合《L,R》,所以加一个判断条件:

    tree[dir].sum + tree[c].ans + tree[c].val >= L && tree[dir].sum + tree[c].ans + tree[c].val <= R

     //c是dir点的一个子结点,sum表示从0结点到该点的距离,ans表示最优子结点的距离

    代码
    #include <iostream>
    using namespace std;

    const long inf = 1000000000;
    const long maxn = 500005;
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a>b?b:a)
    int n,L,R;

    struct node
    {
    int child;
    int father;
    int brother;
    int val;
      int sum;//从0结点到该点的值
    int ans;//子结点到该点的最优值

    void Init()
    {
    child
    = father = brother = -1;
    val
    = 0;sum = 0;ans = 0;
    }
    }tree[maxn];

    void Init()
    {
    int i;
    int a,b,c;
    for(i=0;i<n;i++)
    tree[i].Init();

    for(i=0;i<n-1;i++)
    {
    scanf(
    "%d%d%d",&a,&b,&c);
    tree[b].father
    = a;
    tree[b].brother
    = tree[a].child;
    tree[a].child
    = b;
    tree[b].val
    = c;
    }
    }


    void Sum(int dir)
    {
    int c = tree[dir].child;
    while(c != -1)
    {
    tree[c].sum
    = tree[tree[c].father].sum + tree[c].val;
    Sum(c);
    c
    = tree[c].brother;
    }
    }

    void Bfs(int dir,bool bol)
    {
    if(bol == 0)
    tree[dir].ans
    = 0;
    else
    tree[dir].ans
    = inf;

    int c = tree[dir].child;
    if(c == -1)
    tree[dir].ans
    = 0;
    while(c != -1)
    {
    Bfs(c,
    !bol);
    if(tree[dir].sum + tree[c].ans + tree[c].val >= L && tree[dir].sum + tree[c].ans + tree[c].val <= R)
    {
    if(bol == 0)
    {
    tree[dir].ans
    = max(tree[dir].ans,tree[c].ans + tree[c].val);
    }
    else
    {
    tree[dir].ans
    = min(tree[dir].ans,tree[c].ans + tree[c].val);
    }
    }

    c
    = tree[c].brother;
    }
    }

    void Print()
    {
    if(tree[0].ans >= L && tree[0].ans <= R)
    printf(
    "%d\n",tree[0].ans);
    else
    printf(
    "Oh, my god!\n");
    }

    int main()
    {
    while(scanf("%d%d%d",&n,&L,&R)!=EOF)
    {
    Init();
    Sum(
    0);
    Bfs(
    0,0);
    Print();
    }
    return 0;
    }
  • 相关阅读:
    350 Intersection of Two Arrays II 两个数组的交集 II
    349 Intersection of Two Arrays 两个数组的交集
    347 Top K Frequent Elements 前K个高频元素
    345 Reverse Vowels of a String 反转字符串中的元音字母
    344 Reverse String 反转字符串
    343 Integer Break 整数拆分
    342 Power of Four 4的幂
    338 Counting Bits Bit位计数
    Java常见面试题之Forward和Redirect的区别
    字节、字、bit、byte的关系
  • 原文地址:https://www.cnblogs.com/silencExplode/p/1894101.html
Copyright © 2011-2022 走看看