zoukankan      html  css  js  c++  java
  • Facebook Hacker Cup 2015 Round 1--Corporate Gifting(树动态规划)

    原标题:https://www.facebook.com/hackercup/problems.php?pid=759650454070547&round=344496159068801

    题意:给定一颗有根树,在树上下层的节点要给上层节点礼物,根节点的礼物则给慈善会,可是给礼物有个条件就是你不能送你的父节点已经送出的礼物。问满足要求的最少花费。
    题解:这个题卡了一段时间,相似于染色问题,能够用树形动态规划求解。由于已知节点个数为N,则我们单个节点的最大花费不会超过log2(N) = 18。


    1. 设dp[i][j]是在i节点花费j时以i为根节点的子树所须要的总开销。


    2. 则dp[i][j] = sum{min{dp[son][k],1 <= k <= 18且k != j},son为i的每一个子节点};

    比赛的时候一開始使用DFS,没注意到节点规模在树成链状时会导致暴栈。可是时间已经来不及了,非常遗憾没有进入round 2。

    代码例如以下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define maxN 200005
    #define maxM 18
    
    vector<vector<int> > sons;
    int N;
    int minCost[maxN][maxM];
    
    struct node
    {
        int ID;
        int depth;
        friend bool operator< (node x,node y)
        {
            return x.depth > y.depth;
        }
    }employee[maxN];
    
    int BFS()
    {
        for(int i = 1;i <= N;i++)
        {
            employee[i].ID = i; 
        }
        employee[1].depth = 0;
        int now,next;
        int sonSize;
        queue<int> q;
        q.push(1);
        while(!q.empty())
        {
            now = q.front();
            q.pop();
            sonSize = sons[now].size();
            for(int i = 0;i < sonSize;i++)
            {
                next = sons[now][i];
                q.push(next);
                employee[next].depth = employee[now].depth+1;
            }
        }
    }
    
    int dp()
    {
        int fa,son,sonSize;
        int i,j,k,m;
        int tmpMinCost;
        BFS();
        sort(employee+1,employee+N+1);
        for(i = 1;i <= N;i++)
        {
            fa = employee[i].ID;
            sonSize = sons[fa].size();
            for(j = 1;j <= maxM;j++)
            {
                minCost[fa][j] = j;
                for(k = 0;k < sonSize;k++)
                {
                    son = sons[fa][k];
                    tmpMinCost = INT_MAX;
                    for(int m = 1;m <= maxM;m++)
                    {
                        if(m == j)
                            continue;
                        tmpMinCost = min(tmpMinCost,minCost[son][m]);
                    }
                    minCost[fa][j] += tmpMinCost;
                }
            }
        }
        int ans = INT_MAX;
        for(i = 1;i <= maxM;i++)
        {
            ans = min(ans,minCost[1][i]);
        }
        return ans;
    }
    
    int main()
    {
        freopen("corporate_gifting.txt","r",stdin);
        freopen("out.txt","w",stdout);
        int T;
        int fa;
        scanf("%d",&T);
        for(int i = 1;i <= T;i++)
        {
            scanf("%d",&N);
            vector<vector<int> >().swap(sons);
            sons.resize(N+1);
            for(int j = 1;j <= N;j++)
            {
                scanf("%d",&fa);
                sons[fa].push_back(j);
            }
            printf("Case #%d; %d
    ",i,dp());
        }
        return 0;
    }

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    java_oop_方法2
    POJ 3276 Face The Right Way(反转)
    POJ 3276 Face The Right Way(反转)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3061 Subsequence(尺取法)
    POJ 3061 Subsequence(尺取法)
    HDU 1222 Wolf and Rabbit(欧几里得)
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4882561.html
Copyright © 2011-2022 走看看