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;
    }
    
  • 相关阅读:
    changing a pointer rather than erasing memory cells
    验证码识别 edge enhancement 轮廓增强 region finding 区域查找
    Manipulating Data Structures
    passing parameters by value is inefficient when the parameters represent large blocks of data
    Aliasing 走样
    Artificial Intelligence Research Methodologies 人工智能研究方法
    Thread safety
    include pointers as a primitive data type
    flat file
    functional cohesion
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/5538150.html
Copyright © 2011-2022 走看看