ZOJ 3626 Treasure Hunt I

一道树形DP+01背包的题。用dp[k][j]表示以k的根的树用j天最多可以得到多少宝藏,

m是天数限制,因为要往返,所以将m/2以后就可以直接计算单程的值了。

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <algorithm>



///dp[k][j]表示以k的根的树用j天最多可以得到多少宝藏

using namespace std;

const int MAXN = 105;

int e;

int n, k, m;

int first[MAXN], next[MAXN << 1], v[MAXN << 1];

bool vis[MAXN];

int t[MAXN][MAXN], val[MAXN], dp[MAXN][MAXN];



void addedge(int x, int y)

{

    v[e] = y, next[e] = first[x];

    first[x] = e ++;

}



void ReadGraph()

{

    for(int i = 1; i <= n; i ++)

        scanf("%d", &val[i]);

    e = 0;

    memset(vis, false, sizeof vis);

    memset(first, -1, sizeof first);

    for(int j = 0; j < n - 1; j ++)

    {

        int ui, vi, di;

        scanf("%d%d%d", &ui, &vi, &di);

        t[ui][vi] = t[vi][ui] = di;

        addedge(ui, vi);

        addedge(vi, ui);

    }

    scanf("%d%d", &k, &m);

    m /= 2;

}



void dfs(int k)

{

    int i, j, x, s;

    vis[k] = true;

    for(s = first[k]; s != -1; s = next[s])

    {

        x = v[s];

        if(!vis[x])

        {

            dfs(x);

            for(j = m; j >= t[k][x]; j --) //从k有足够的时间去x点

                for(i = 0; i <= j - t[k][x]; i ++)

                {

                    dp[k][j] = max(dp[k][j], dp[k][j - t[k][x] - i] + dp[x][i]);

                }

        }

    }

}



int main()

{

    while(scanf("%d", &n) == 1)

    {

        ReadGraph();

        for(int i = 1; i <= n; i ++)

            for(int j = 0; j <= m; j ++)

                dp[i][j] = val[i];

        dfs(k);

        printf("%d\n", dp[k][m]);

    }

    return 0;

}

 

 

 

你可能感兴趣的:(ZOJ)