zoukankan      html  css  js  c++  java
  • hiho_1055_刷油漆

    题目大意

        一棵树,每个节点都有相应的value值。从根开始选择M个节点相互连通,使得这些节点的value值之和最大。 
    题目链接:[刷油漆][1]

    题目分析

        典型的树形dp,dp[i][j] 表示以节点i为根的子树中选择j个节点(从i节点出发)相互连通,所能达到的节点value之和的最大值。可以很容易知道, 
    dp[root][k] = max{dp[ch1][k1] + dp[ch2][k2] + .. dp[cht][kt]}. 
    即将k-1个节点分配给 根节点root的t个子节点,其中 k1 + k2 + .. + kt = k -1. 
        看起来要枚举 ch1, ch2...cht 所能分配到的节点数k1, k2...kt 的所有情况,但这可以利用有限背包问题类似的做法, 在进行dfs方式求解时,每求解完根节点root的一个子节点 ch,就可以类似背包问题来进行 
    状态优化。

    //dp[node][i]表示以node为根的子树中选择i个节点,且节点相互连通,所能达到的value和的最大值。
    //注意i要从大到小进行枚举,且j一定小于i,不能等于i,因为node节点必须被占用
    for (int i = M; i >= 2; i--) {
        for (int j = 1; j < i; j++) {
            dp[node][i] = dp[node][i] > dp[node][i - j] + dp[v][j] ? dp[node][i] : dp[node][i - j] + dp[v][j];
            }
    }
    

     实现

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    struct Edge {
    	int to;
    	int next;
    };
    
    int gNodeValue[105];
    int dp[105][105];
    int gHead[105];
    bool gVisited[105];
    int gValue[105];
    Edge gEdges[220];
    int gEdgeIndex;
    
    void InsertEdge(int u, int v) {
    	int e = gEdgeIndex++;
    	gEdges[e].to = v;
    	gEdges[e].next = gHead[u];
    	gHead[u] = e;
    
    	e = gEdgeIndex++;
    	gEdges[e].to = u;
    	gEdges[e].next = gHead[v];
    	gHead[v] = e;
    }
    int min(int a, int b) {
    	return a < b ? a : b;
    }
    void Dfs(int node, int m) {
    	gVisited[node] = true;
    	int e = gHead[node];
    	dp[node][1] = gValue[node];
    	for (e; e != -1; e = gEdges[e].next) {
    		int v = gEdges[e].to;
    		if (!gVisited[v]) {
    			Dfs(v, m);
    			for (int i = m; i >= 2; i--) {
    				for (int j = 1; j < i; j++) {
    					dp[node][i] = dp[node][i] > dp[node][i - j] + dp[v][j] ? dp[node][i] : dp[node][i - j] + dp[v][j];
    				}
    			}
    			
    		}
    	}	
    }
    
    void Init() {
    	memset(gValue, 0, sizeof(gValue));
    	memset(dp, 0, sizeof(dp));
    	memset(gValue, false, sizeof(gVisited));
    	memset(gEdges, -1, sizeof(gEdges));
    	gEdgeIndex = 0;
    	memset(gSuccessorNum, 0, sizeof(gSuccessorNum));
    	memset(gHead, -1, sizeof(gHead));
    }
    
    int main() {
    	int n, m;
    	Init();
    	scanf("%d %d", &n, &m);
    	for (int i = 1; i <= n; i++) {
    		scanf("%d", &gValue[i]);
    	}
    	int u, v;
    	for (int i = 1; i < n; i++) {
    		scanf("%d %d", &u, &v);
    		InsertEdge(u, v);
    	}
    	Dfs(1, m);
    	printf("%d
    ", dp[1][m]);
    	return 0;
    }
    
  • 相关阅读:
    数据库设计Step by Step篇目整理及下载地址
    SQL puzzles and answers读书笔记——预算执行问题
    MongoDB快速入门——SQL与MongoDB的对照
    C语言中的atan和atan2
    FTP命令
    vueelementadmin前端跨域问题解决
    回归
    学习kvm(一)
    利用spicevdagent实现文本拷贝、鼠标非陷入
    政策转向确立,降准只是开始
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/5538150.html
Copyright © 2011-2022 走看看