zoukankan      html  css  js  c++  java
  • 树形dp

    A - Anniversary party

    这个题目是说,公司开宴会,为了让这个宴会的欢乐值尽量大,所以我们规定每一个员工的直属上司不能去,或者说每一个上司的直属员工不能去 , 然后求这个宴会的最大快乐值。

    这个题目是我树形dp的入门题吧,虽然我到现在都还是不太懂树形dp,感觉就是模模糊糊的一个理解。

    dp[i][0]:表示不邀请i员工其子树达到的最大快乐值,dp[i][1]则表示邀请。

    其实我也不太懂为什么是这样定义的,不过暂时就这么想着吧。

    这个需要建图,然后就是在树上进行dp。

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <iostream>
    using namespace std;
    const int maxn = 6e3 + 10;
    vector<int>G[maxn];
    int a[maxn];
    int f[maxn];
    int dp[maxn][2];
    
    void dfs(int u)
    {
        for(int i=0;i<G[u].size();i++)
        {
            dfs(G[u][i]);
        }
        for(int i=0;i<G[u].size();i++)
        {
            dp[u][0] += max(dp[G[u][i]][0], dp[G[u][i]][1]);
            dp[u][1] += dp[G[u][i]][0];
        }
    }
    
    int main()
    {
        int n;
        scanf("%d", &n);
        memset(f, -1, sizeof(f));
        for (int i = 1; i <= n; i++) scanf("%d", &dp[i][1]);
        int so, fa;
        while(scanf("%d%d",&so,&fa)==2&&(so+fa))
        {
            G[fa].push_back(so);
            f[so] = 1;
        }
        int root = 0;
        for(int i=1;i<=n;i++)
        {
            if (f[i] == -1) root = i;
        }
        dfs(root);
        printf("%d
    ", max(dp[root][0], dp[root][1]));
        return 0;
    }
    A

    B - Strategic game POJ - 1463 

    这个题目和上面那个是一个意思,可以一样的进行dp,状态转移方程只是微变。

    #include <cstdio>
    #include <cstdlib>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn = 1e5 + 10;
    typedef long long ll;
    int dp[maxn][10];
    vector<int>G[maxn];
    bool vis[maxn];
    
    void dfs(int u)
    {
        for(int i=0;i<G[u].size();i++)
        {
            dfs(G[u][i]);
        }
        for(int i=0;i<G[u].size();i++)
        {
            dp[u][0] += dp[G[u][i]][1];
            dp[u][1] += min(dp[G[u][i]][0], dp[G[u][i]][1]);
        }
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            memset(dp, 0, sizeof(dp));
            for (int i = 0; i <= n; i++) {
                G[i].clear();
                vis[i] = 0;
                dp[i][1] = 1;
            }
            for(int i=1;i<=n;i++)
            {
                int u, v, cnt;
                scanf("%d:(%d)", &u, &cnt);
                for(int j=1;j<=cnt;j++)
                {
                    scanf("%d", &v);
                    G[u].push_back(v);
                    vis[v] = 1;
                }
            }
            int root = 0;
            for (int i = 0; i < n; i++) if (vis[i] == 0) {
                root = i;
                break;
            }
            dfs(root);
            printf("%d
    ", min(dp[root][1], dp[root][0]));
        }
        return 0;
    }
    B

    C - Tree Cutting POJ - 2378 

    题目大意:给一颗n个结点的树,节点编号为1~n,问删除一个节点之后,让剩下的分支中节点数量最多的尽量少。可能有多种方案,按编号顺序输出。

    这个题目说是一个树形dp,但是我感觉更像是一个搜索的思维题,

    这个题目说是要删去一部分节点,使得之后形成的联通块的所有节点小于等于n/2

    这个我们可以把任何一个点当作是根节点,所以我们只要求出这个根节点的子树的节点最大也要小于等于n/2就是满足条件的节点。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <queue>
    #include <algorithm>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn = 1e4 + 10;
    int dp[maxn], num[maxn];
    vector<int>G[maxn];
    int n;
    
    int dfs1(int u,int pre)
    {
        int sum = 1;
        for(int i=0;i<G[u].size();i++)
        {
            if (G[u][i] == pre) continue;
            int res=dfs1(G[u][i], u);
            sum += res;
            num[u] = max(num[u], res);
        }
        num[u] = max(num[u], n - sum);
        return sum;
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=1;i<=n-1;i++)
            {
                int u, v;
                scanf("%d%d", &u, &v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
            dfs1(1, -1);
            for(int i=1;i<=n;i++)
            {
                if (num[i] <= n / 2) printf("%d
    ", i);
            }
        }
        return 0;
    }
    C
  • 相关阅读:
    Tomcat源码(二):tomcat启动之前的初始化
    Tomcat源码(一):整体架构
    SSH的三个组件ssh、sftp、scp介绍
    远程连接linux服务上的mysql
    linux系统上安装mysql5.6(详细步骤)
    一种基于数字证书的单点登录的实现方法(转)
    jacob操作word (转)
    解决fis3下载慢,没反应
    Spring框架集成mybatis框架的配置(笔记)
    eclipse导入lombok后打不开(如果你的lombok不是最新的,那就来下载最新的)
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/10978143.html
Copyright © 2011-2022 走看看