• Hihocoder 1063 缩地


    树形dp
    涉及不重复背包组合求最小
    从边长分段看不好入手
    因为点数只有100点值<=2,总值<=200
    可以对每个点的每个值进行dp
    这里最后不回来肯定优于全回来
    然后由于要分为回来和不回来两种情况要分别dp,因为不回来会要用到回来的
    不回来的可以按不回来的最小+去掉不回来那个子节点的回来的最小进行dp
    另外注意下上下限和初始值

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int N = 205;
    int vec[N];
    struct Edge{
    	int v, len, nxt;
    }edge[N];
    int cnt;
    int head[N];
    int dp[2][N][N];
    void addedge(int u, int v, int value) {
    	edge[cnt] = Edge{ v,value,head[u] };
    	head[u] = cnt++;
    	edge[cnt] = Edge{ u,value,head[v] };
    	head[v] = cnt++;
    }
    void dfs(int u,int p) {
    	dp[0][u][vec[u]] = 0;
    	dp[1][u][vec[u]] = 0;
    	for (int t = head[u]; t != -1; t = edge[t].nxt) {
    		Edge e = edge[t];
    		if (e.v == p)
    			continue;
    		dfs(e.v, u);	
    
    		int v = e.v;
    		for (int i = 200; i >= 0; i--)
    		{
    			for (int j = 0; j <= i; j++) {
    				dp[0][u][i] = min(dp[0][u][i],dp[0][u][j] + dp[0][v][i-j]+2*e.len);
    			}
    		}
    	}	
    	for (int t = head[u]; t != -1; t = edge[t].nxt) {
    		Edge e = edge[t];
    		int v = e.v;
    		if (v == p)
    			continue;
    		int sum[N];
    		for (int i = 0; i <= 202; i++)
    			sum[i] = 1e9;
    		sum[vec[u]] = 0;
    		for (int t2 = head[u]; t2 != -1;t2=edge[t2].nxt) {
    			Edge e2 = edge[t2];
    			int v2 = e2.v;
    			if (v2==p || v2 == v)
    				continue;
    			
    			for (int i = 200; i >= 0; i--){
    				for (int j = 0; j <= i; j++) {
    					sum[i] = min(sum[i], sum[j] + dp[0][v2][i - j]+2*e2.len);
    				}
    			}
    		}
    		for (int i = 200; i >= 0; i--) {
    			for (int j = 0; j <= i; j++) {
    				dp[1][u][i] = min(dp[1][u][i], dp[1][v][j] + sum[i - j]+e.len);
    			}
    		}			
    	}	
    }
    int main() {  
    	int n;
    	cin >> n;
    	cnt = 1;
    	for (int i = 1; i <= n; i++) {
    		cin >> vec[i];
    	}
    	memset(head, -1, sizeof head);
    	for (int i = 0; i < 2; i++)
    		for (int j = 0; j <= 200; j++)
    			for (int k = 0; k <= 200; k++)
    				dp[i][j][k] = 1e9;
    
    	for (int i = 0; i < n - 1; i++) {
    		int sv, ev, w;
    		cin >> sv >> ev >> w;
    		addedge(sv,ev,w);
    	}
    	dfs(1, 0);
    	int m;
    	cin >> m;
    	while(m--){
    		int x;
    		cin >> x;
    		for (int i = 200; i >=0; i--)
    			if (dp[1][1][i] <= x)
    			{
    				printf("%d
    ", i);
    				break;
    			}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Multi ingress controller
    Obtain file system information
    What is the difference between “inode size” and “Bytes per inode”
    Build and install fluent-bit on CentOS7
    Failed to initialize NVML: Driver/library version mismatch.
    利用multiprocessing.managers开发跨进程生产者消费者模型
    [算法] 举一反三之n重复数组中找唯一m重复异类数
    HBase Thrift过滤语法
    kubernetes pod infra container网络原理
    CentOS7上手动部署入门级kubernetes
  • 原文地址:https://www.cnblogs.com/HaibaraAi/p/6221144.html
Copyright © 2020-2023  润新知