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;
    }

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

  • 相关阅读:
    轻松学习Linux之AWK使用初步
    轻松学习Linux之理解Shell的硬链接与软连接
    轻松学习Linux之自动执行任务
    轻松学习Linux系统安装篇之fdisk命令行工具的使用
    Leetcode-1030 Next Greater Node In Linked List(链表中的下一个更大节点)
    Leetcode-1028 Convert to Base -2(负二进制转换)
    Leetcode-1029 Binary Prefix Divisible By 5(可被 5 整除的二进制前缀)
    ACM模板——2的次方表
    ACM模板——快速幂
    ACM模板——素数相关
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4882561.html
Copyright © 2011-2022 走看看