• poj2486 Apple Tree【区间dp】


    转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4374766.html   ---by 墨染之樱花

    【题目链接】http://poj.org/problem?id=2486

    【题目描述】给一张顶点带权值的图,求从1号点出发走k步的最大总权值(顶点可以重复走)

    【思路】经典的树形dp,本沙茶看了别人的题解才会orz。。。。详情请见下面的代码中的详细注释

    /* ***********************************************
    Author        :Kirisame_Marisa
    blog          :http://www.cnblogs.com/KirisameMarisa/
    Created Time  :2015年03月28日 星期六 18时56分45秒
    File Name     :c.cpp
    ************************************************ */
    
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int MAXN=1000;
    #define eps 1e-10
    #define zero(x) (fabs(x)<eps)
    #define REP(X,N) for(int X=0;X<N;X++)
    #define REP2(X,L,R) for(int X=L;X<=R;X++)
    #define CLR(A,X) memset(A,X,sizeof(A))
    #define PB(X) push_back(X)
    #define MP(X,Y) make_pair(X,Y)
    #define IT iterator
    #define test puts("OK")
    typedef long long ll;
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    typedef vector<PII> VII;
    
    int a[110];
    VI G[110];
    int V,k;
    int dp[110][210][2];    //dp[i][j][t]在i为根的子树中走k步,t=0表示不回到根,t=1表示回到根
    
    void dfs(int u,int par)
    {
        REP(i,G[u].size())
        {
            int v=G[u][i];
            if(v==par)
                continue;
            dfs(v,u);
            for(int j=k;j>=1;j--)
            {
                //回到u只有一种情况:先后在v根子树中走p步,其他子树中走j-p-2步
                REP2(p,0,j-2)        //p表示在以v为根的子树中走p步,由于uv两点来回要两步,所以范围显然是0到j-2,下同
                    if(dp[u][j-p-2][1]+dp[v][p][1]>dp[u][j][1])
                        dp[u][j][1]=dp[u][j-p-2][1]+dp[v][p][1];
                //不回到u有两种情况:1.u到v,在v子树中转一圈回到v,再回到u,最后走其他子树不再回来
                REP2(p,0,j-2)
                    if(dp[u][j-p-2][0]+dp[v][p][1]>dp[u][j][0])
                        dp[u][j][0]=dp[u][j-p-2][0]+dp[v][p][1];
                                  //2.走其他子树回到u,再到v,在v子树中不回来(会不会到v都行,因为只要不再回u,不过不考虑这个也能AC -_-b)
                REP2(p,0,j-1)        //由于uv之间只要走一次u到v,所以范围是0到j-1
                    if(dp[u][j-p-1][1]+max(dp[v][p][0],dp[v][p][1])>dp[u][j][0])
                        dp[u][j][0]=dp[u][j-p-1][1]+max(dp[v][p][0],dp[v][p][1]);
            }
        }
    }
    
    int main()
    {
        //freopen("in","r",stdin);
        //freopen("out","w",stdout);
        while(~scanf("%d%d",&V,&k))
        {
            REP(i,V)
                G[i].clear();
            REP(i,V)
                scanf("%d",&a[i]);
            REP(i,V)
                REP2(j,0,k)
                    dp[i][j][0]=dp[i][j][1]=a[i];   //初始化
            REP(i,V-1)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                x--;y--;
                G[x].PB(y);
                G[y].PB(x);
            }
            dfs(0,-1);
            printf("%d
    ",max(dp[0][k][0],dp[0][k][1]));
        }
        return 0;
    }
    代码君
  • 相关阅读:
    org.apache.zookeeper.ClientCnxn
    Oracle数据库 number 长度与 Short Integer Long BigDecimal 对应关系
    Spring中 PROPAGATION_REQUIRED 解释
    java的static final和final的区别
    本地调试有数据,发布到服务器没更新的问题
    java的double类型如何精确到一位小数?
    consul配置参数大全、详解、总结
    深入对比TOML,JSON和YAML
    基于Jenkins,docker实现自动化部署(持续交互)【转】
    让Linux任务在后台可靠运行的几种方法
  • 原文地址:https://www.cnblogs.com/KirisameMarisa/p/4374766.html
Copyright © 2020-2023  润新知