• 牛客提高 杀树


    https://ac.nowcoder.com/acm/contest/5389/D

    我也不敢说我学会了,说说总结的经验吧。

    当假设dp[a][b],dp内部状态是小于等于b的时候,不必枚举b,只要让b尽可能大然后取dp[a][b] = min(dp[a][b-1],dp[a][b])就行了

    应该就是这样了,代码方下来,以后多看几天

    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<string>
    using namespace std;
    const int maxn = 5050 + 11;
    typedef long long ll;
    
    vector<int>G[maxn];
    void add(int be, int en) {
    	G[be].push_back(en);
    }
    ll dp[maxn][maxn];
    
    int list[maxn];
    int k;
    
    int dfs(int x, int fa) {
    	dp[x][0] = list[x];
    	for (int s = 0; s < G[x].size(); s++) {
    		int p = G[x][s];
    		if (p == fa) continue;
    		dfs(p, x);
    		dp[x][0] += dp[p][k - 1];
    	}
    
    	for (int i = 1; i < k; i++) {
    		ll tp = 0;
    		for (int j = 0; j < G[x].size(); j++) {
    			int p = G[x][j];
    			if (p == fa) continue;
    			dp[x][i] = min(dp[x][i] + dp[p][min(i - 1, k - i - 1)], dp[p][i - 1] + tp);
    
    			tp += dp[p][min(i - 1, k - i - 1)];
    		}
    		dp[x][i] = min(dp[x][i], dp[x][i - 1]);
    	}
    
    	return 0;
    }
    
    
    
    int main() {
    	int n;
    	scanf("%d %d", &n, &k);
    	for (int i = 1; i <= n; i++) {
    		scanf("%d", &list[i]);
    	}
    	for (int i = 1; i < n; i++) {
    		int be, en;
    		scanf("%d %d", &be, &en);
    		add(be, en);
    		add(en, be);
    	}
    	dfs(1, -1);
    	cout << dp[1][k - 1] << endl;
    	return 0;
    }
    
    /*
    6 3
    1 2 3 4 5 6
    1 2
    2 5
    3 5
    5 6
    6 4
    
    输出5
    
    */
    

      

  • 相关阅读:
    图片《小美眉》
    redhat基本知识
    Linux 求助。设置分辨率?

    PHP close
    别想一个人承担一切
    java charAt返回char,不是int
    我的计算器
    支付宝面试小贴士
    java string charAt length()疑惑
  • 原文地址:https://www.cnblogs.com/lesning/p/14090305.html
Copyright © 2020-2023  润新知