• Apple Tree


    【题目描述】

    一棵苹果树有N(1 <= N <= 100)个节点(编号为1~N),每个节点上都有一定数量的苹果,Mary从根节点(编号为1)开始通过K(0 <= K <= 200)个结点,每通过一个节点,她就可以把此节点上的苹果吃掉,询问Mary最多能够吃掉多少个苹果。

    【输入描述】

    输入多组数据,每组数据格式如下:

    第一行输入两个数N、K;

    第二行输入N个数,表示每个节点上的苹果数量;

    接下来N-1行,每行输入两个数A、B,表示节点A和节点B相连。

    【输出描述】

    对于每组数据,输出一个数,表示答案。

    【输入样例】

    2 1

    0 11

    1 2

    3 2

    0 1 2

    1 2

    1 3

    【输出样例】

    11

    2

    源代码:
    
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct Node
    {
        int To,Next;
    }i[501];
    int n,k,Num,f[201][401][2],Head[201],W[201];
    void Add(int t1,int t2) //边表。
    {
        i[++Num].To=t2;
        i[Num].Next=Head[t1];
        Head[t1]=Num;
    }
    void DFS(int Root,int Mark)
    {
        for (int a=Head[Root];a;a=i[a].Next)
        {
            int T=i[a].To;
            if (T==Mark) //无向边判重。
              continue;
            DFS(T,Root); //DFS回溯。
            for (int b=k;b>=1;b--) //倒序以防重复。
              for (int c=1;c<=b;c++) //断点。
              {
                f[Root][b][0]=max(f[Root][b][0],f[Root][b-c][1]+f[T][c-1][0]); //仔细想想这些常数的含义。
                f[Root][b][0]=max(f[Root][b][0],f[Root][b-c][0]+f[T][c-2][1]);
                f[Root][b][1]=max(f[Root][b][1],f[Root][b-c][1]+f[T][c-2][1]);
              }
        }
    }
    int main()
    {
        while (scanf("%d%d",&n,&k)==2)
        {
            Num=0;
            memset(f,0,sizeof(f));
            memset(Head,0,sizeof(Head)); //初始化。
            for (int a=1;a<=n;a++)
            {
                scanf("%d",&W[a]);
                for (int b=0;b<=k;b++)
                  f[a][b][0]=f[a][b][1]=W[a]; //赋初值。
            }
            for (int a=1;a<n;a++)
            {
                int t1,t2;
                scanf("%d%d",&t1,&t2);
                Add(t1,t2);
                Add(t2,t1);
            }
            DFS(1,0);
            printf("%d
    ",max(f[1][k][0],f[1][k][1]));
        }
        return 0;
    }
    
    /*
        设f[i][j][0]表示以i为根节点,走j步,不回到i点的能够得到的最大苹果数,f[i][j][1]表示回到i点的。
        则f[i][j][0]可以存在2种转移:
            (1)走i的其他一些子树,然后返回i,再走T子树,不返回;
            (2)走T子树,然后返回i,再走i的其他一些子树,不返回;
        以此类推,f[i][j][1]可以存在1种转移:
            走T子树,然后返回i,再走i的其他一些子树,返回i;
        可得状态转移方程:
            f[i][j][0]=max(f[i][j-k][0]+f[i][k-2][1],f[i][j-k][1]+f[i][k-1][0]);
            f[i][j][1]=max(f[i][j-k][1]+f[i][k-2][1]);
    */
  • 相关阅读:
    反射之初认识
    面向对象(上)练习一 改进:调用方法
    关于php中id设置自增后不连续的问题
    由于定界符引出的格式错误问题
    PHP 关于timezone问题
    2016.4.29 园子第一天,希望所有的坚持都有所收获
    递归调用
    动手动脑
    界面实验任务
    课程作业02
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5977750.html
Copyright © 2020-2023  润新知