• 【u228】圣诞树


    【问题描述】
    圣诞特别礼物挂在一棵圣诞树上,这棵树有n层,每层有一件礼物,每件礼物都有一个价值,有的礼物还有一些连结线,与下层的礼物相连,领取礼物的规则如下:任选一件礼物,它的下面如果有连结线,则可以继续取它连结的礼物,以此类推,直至取到没有连结线的礼物才结束,你如果是第一个去取,怎样取才能获得最大的价值呢?请你编一程序解决这一问题。
    【输入文件】
    输入文件tree.in的第一行只有一个数据n(n<=100),表示有n层礼物,以下有n行数据,分别表示第1-n层礼物的状态,每行至少由一个数据构成,且第一个数据表示该礼物的价值,后面的数据表示它与哪些层的礼物相连,如果每行只有一个数据则说明这层礼物没有与下层礼物相连,每个数的大小均不超过10000。
    【输出文件】
    输出文件tree.out也只有一个数,表示获得的取大价值。
    【输入样例】
    3
    12 2 3
    20
    30
    【输出样例】
    42
    【题目链接】:http://noi.qz5z.com/viewtask.asp?id=u228

    【题解】

    设f[x]表示选第x层的礼物能够获得的最大价值;
    f[x] = a[x];
    f[x] = max(f[x],f[x]+max(f[x的儿子节点]);
    最后1..n取最大的f值;
    一棵树可能有多个根;
    之前算过的f值就不要重复算了.
    一行里面有未知个数的数字的;
    可以用cin.peek()函数来判断是不是读到了行末

    【完整代码】

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <algorithm>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%I64d",&x)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    const int MAXN = 110;
    
    int n;
    int a[MAXN],f[MAXN];
    vector <int> g[MAXN];
    bool bo[MAXN];
    
    void dfs(int x)
    {
        f[x] = a[x];
        bo[x] = true;
        int len = g[x].size(),temp = -21e8;
        rep1(i,0,len-1)
        {
            int y = g[x][i];
            if (!bo[y])
                dfs(y);
            temp = max(temp,f[y]);
        }
        if (temp>0)
            f[x]+=temp;
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        cin >> n;
        char t = getchar();//把换行符给读了
        rep1(i,1,n)
        {
            int x;
            rei(a[i]);
            while (cin.peek()!=EOF)
            {
                if (isdigit(cin.peek()))
                {
                    cin >> x;
                    g[i].pb(x);
                }
                if (cin.peek()=='
    ')
                    break;
                cin.ignore();
            }
            t = getchar();
        }
        rep1(i,1,n)
            if (!bo[i])
            {
                dfs(i);
            }
        int ans = f[1];
        rep1(i,2,n)
            ans = max(ans,f[i]);
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    高校手机签到系统——Ksoap2的一些使用心得(补充)
    高校手机签到系统——zxing.net生成二维码(补充)
    高校手机签到系统——手机客户端
    高校手机签到系统——第一部分Authority权限系统(下)
    高校手机签到系统——第一部分Authority权限系统(上)
    《算法导论》——顺序统计RandomizedSelect
    《算法导论》——计数排序Counting Sort
    [Asp.Net Core] Blazor Server Side 项目实践
    [Asp.Net Core] Blazor Server Side 开发教程
    视频图文教学
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626653.html
Copyright © 2020-2023  润新知