• 【CSP模拟】小凯的疑惑(DP)



    首先,这道题正解的思路是从subtask2而得来的,所以先讲一下subtask2的做法。

    因为保证答案不超过long long,所以直接求最大权独立集即可:dp[u][0]表示u点一定不能取的答案,dp[u][1]表示u点对儿子没有限制的答案。

    (dp[u][0]=max(dp[v][0],dp[v][1]))

    (dp[u][1]=max(dp[u][1],val[u]*prod dp[v][0]))

    直接跑DP即可。

    而正解是怎么做的呢?

    想到乘法,可以将其转化为对数,每次乘法就相当于对数相加,这个就可以计算出怎样选取这个最大权独立集,再跑一遍深搜统计答案即可。

    //这里的dp的都是对数,所以只用相加即可
    void dfs(int u,int fa)
    {
        dp[u][0]=dp[u][1]=0;
        for(int i=head[u];i;i=nxt[i])
        {
            int v=to[i];
            if(v!=fa)
            {
                dfs(v,u);
                dp[u][0]+=max(dp[v][0],dp[v][1]);
                dp[u][1]+=dp[v][0];
            }
        }
        dp[u][1]+=logv[u];
    }
    
    \统计答案的时候通过已经求出来的dp来作决策
    
    \如果u本身被选,肯定儿子不可选
    
    \如果u本身没有被选,判断儿子选更优还是不选更优。
    
    \选的话要乘上val
    
    long long dfs1(int u,int fa,int yes)
    {
        long long ans=1;
        for(int i=head[u];i;i=nxt[i])
        {
            int v=to[i];
            if(v!=fa)
            {
                if(yes)
                {
                    ans=(ans*dfs1(v,u,0))%mod;
                }else{
                    if(dp[v][0]>dp[v][1])
                    {
                        ans=(ans*dfs1(v,u,0))%mod;
                    }else{
                        ans=(ans*dfs1(v,u,1))%mod;
                    }
                }
            }
        }
        if(yes)
        {
            ans=(ans*val[u])%mod;
        }
        return ans;
    }
    
    if(dp[1][0]>dp[1][1])
    {
        printf("%lld
    ",dfs1(1,-1,0));
    }else{
        printf("%lld
    ",dfs1(1,-1,1));
    }
    
  • 相关阅读:
    冲刺周期会议三
    冲刺周期会议二
    冲刺周期会议一
    日常会议
    总结会议及站立会议(六)
    站立会议(五)
    站立会议(四)
    【自习任我行】
    软件小创意
    团队项目题目拟定
  • 原文地址:https://www.cnblogs.com/2017gdgzoi44/p/11824168.html
Copyright © 2020-2023  润新知