• hdu 4003 Find Metal Mineral(树形DP)


    题意:给定一棵树,每条边都有各自的权值,要求用K个机器人(从根出发),遍历整棵数,求最小总权值

    分析:一开始很清楚的知道,还是一道树形背包,用dp[i][j]表示以节点i为根的子树选了j个机器人遍历的权值和。

    关键在j==0 时的意义的理解,一开始总处理不好,就是dp[i][0]表示的是以i为根的子树放置一个机器人遍历完子树之后又回到i

    View Code
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<vector>
    using namespace std;
    const int N = 10010;
    int n,K,S;
    __int64 dp[N][11];
    bool vis[N];
    struct edge
    {
    int v,w;
    edge(){}
    edge(int a,int b):v(a),w(b){}
    };
    vector<edge> g[N];
    void init()
    {
    for(int i=0;i<=n;i++)
    g[i].clear();
    memset(dp,0,sizeof(dp));
    memset(vis,false,sizeof(vis));
    }
    void dfs(int u)
    {
    int size=g[u].size();
    if(size==0)
    return ;
    for(int i=0;i<size;i++)
    {
    int v=g[u][i].v;
    if(vis[v]) continue;
    vis[v]=true;
    dfs(v);
    for(int j=K;j>=0;j--)
    {
    dp[u][j]+=dp[v][0]+g[u][i].w*2;//v所在子树不放置机器人,这个要单独处理,同时也是因为,每一个分支都要遍历到
    for(int k=1;k<=j;k++)//子树放置1~j个机器人
    dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k]+k*g[u][i].w);
    }
    }
    }
    int main()
    {
    int x,y,w;
    while(scanf("%d %d %d",&n,&S,&K)==3)
    {
    init();
    for(int i=1;i<n;i++)
    {
    scanf("%d %d %d",&x,&y,&w);
    g[x].push_back(edge(y,w));
    g[y].push_back(edge(x,w));
    }
    vis[S]=true;
    dfs(S);
    printf("%I64d\n",dp[S][K]);
    }
    return 0;
    }
  • 相关阅读:
    自主问题--KMP算法
    题解--luogu--CSP2019.S.Day2.T4--Emiya 家今天的饭
    浅谈——RMQ
    浅谈——LCA
    NOIP(si le)或者CSP初赛之——前序中序后序,前缀中缀后缀
    浅说——查分约束
    浅说——tarjan
    C++ RQNOJ 星门龙跃
    C++ 洛谷 1261:【例9.5】城市交通路网
    刷题
  • 原文地址:https://www.cnblogs.com/nanke/p/2382943.html
Copyright © 2020-2023  润新知