zoukankan      html  css  js  c++  java
  • 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;
    }
    代码君
  • 相关阅读:
    49. 字母异位词分组
    73. 矩阵置零
    Razor语法问题(foreach里面嵌套if)
    多线程问题
    Get json formatted string from web by sending HttpWebRequest and then deserialize it to get needed data
    How to execute tons of tasks parallelly with TPL method?
    How to sort the dictionary by the value field
    How to customize the console applicaton
    What is the difference for delete/truncate/drop
    How to call C/C++ sytle function from C# solution?
  • 原文地址:https://www.cnblogs.com/KirisameMarisa/p/4374766.html
Copyright © 2011-2022 走看看