zoukankan      html  css  js  c++  java
  • hihoCoder#1055 : 刷油漆 (树形DP+01背包)

    题目大意:给一棵带点权的树,现在要从根节点开始选出m个连通的节点,使总权值最大。

    题目分析:定义状态dp(u,m)表示在以u为根的子树从根节点开始选出m个点连通的最大总权值,则dp(u,m)=max(dp(u,m),dp(u,m-k)+dp(son,k)),其中0<=k<m。这是01背包,k应该从大往小枚举。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<vector>
    # include<list>
    # include<queue>
    # include<map>
    # include<set>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    const int N=1000;
    const int INF=1000000000;
    const double inf=1e20;
    
    int n,m;
    int w[105];
    vector<int>e[105];
    int dp[105][105];
    
    void dfs(int u,int fa)
    {
    	fill(dp[u],dp[u]+m+1,w[u]);
    	dp[u][0]=0;
    	for(int i=0;i<e[u].size();++i){
    		int v=e[u][i];
    		if(v==fa) continue;
    		dfs(v,u);
    		for(int j=m;j>=2;--j){
    			for(int k=j-1;k>=0;--k)
    				dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
    		}
    	}
    }
    
    int main()
    {
    	while(~scanf("%d%d",&n,&m))
    	{
    		for(int i=0;i<n;++i){
    			scanf("%d",w+i);
    			e[i].clear();
    		}
    		int a,b;
    		for(int i=1;i<n;++i){
    			scanf("%d%d",&a,&b);
    			--a,--b;
    			e[a].push_back(b);
    			e[b].push_back(a);
    		}
    		dfs(0,-1);
    		printf("%d
    ",dp[0][m]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    JavaScript将数字转换为大写金额
    css浮动
    JS合并数组的几种方法及优劣比较
    jquery.zclip.js粘贴功能
    iframe获取元素
    某些框架,类库
    web前端基础知识!
    前端开发流程
    学习其他前端技术
    SVN的学习以及使用!
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5485127.html
Copyright © 2011-2022 走看看