zoukankan      html  css  js  c++  java
  • HDU 5534 Partial Tree 完全背包

    题意:

    让你构造一个有(n(2 leq n leq 2015))个节点的树。
    然后定义这棵树的(coolness)(sum{f(d)}),其中(d)是每个节点的度数,函数(f)在输入中给出。

    分析:

    一颗含有(n)个节点的树,有(n-1)条边,度数之和为(2n-2)
    所以我们可以转化成一个完全背包问题:

    背包的容量为(2n-2),我们要恰好选(n)个物品而且要恰好装满背包。体积为(i)的物品的价值为(f(i)),而且每种物品有无穷多个。
    所以可以设计出类似的状态:(d(i, j))表示选了(i)件物品,体积为(j)时所能得到的最大价值。
    最后发现总的时间复杂度是(O(n^3))的。

    分析原因:问题就在于转移的过程会有很多相同的状态。比如背包里的物品为((1, 2, 3)),这个状态可以由((1, 2))后面加个(3)得到,也可以由((1, 3))后面加个(2)得到。事实上具体是由什么顺序转移过来我们是不关心的,我们只关系每种物品选了多少件。

    参考叉姐的思路
    一开始假设大家的度数都为(1),然后慢慢地增大,让大家的度数和增大到(2n-2)
    设计新的状态(d(i, j))表示已经考虑过增大到(leq i)的度数,总度数和为(j),能得到的最大价值。
    那么有状态转移方程:$d(i,j)=max { (d(i-1,j),d(i,j-(i-1))+f(i)-f(1)) } ( 最终所求的答案就是)d(n-1,n-2)$

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 2050;
    
    int n;
    int f[maxn];
    //滚动数组优化一下空间
    int d[2][maxn];
    
    int main()
    {
    	int T; scanf("%d", &T);
    	while(T--) {
    		scanf("%d", &n);
    		for(int i = 1; i < n; i++) scanf("%d", f + i);
    		memset(d, 0, sizeof(d));
    		int cur = 1;
    		d[1][0] = n * f[1];
    		for(int i = 2; i <= n - 1; i++) {
    			cur ^= 1;
    			memset(d[cur], 0, sizeof(d[cur]));
    			for(int j = 0; j < i - 1; j++) d[cur][j] = d[cur^1][j];
    			for(int j = i - 1; j <= n - 2; j++)
    				d[cur][j] = max(d[cur^1][j], d[cur][j-i+1] + f[i] - f[1]);
    		}
    
    		printf("%d
    ", d[cur][n - 2]);
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    Hard Rock
    Codeforces Round #416 (Div. 2) B. Vladik and Complicated Book
    codeforces 793B. Igor and his way to work
    codeforces 1B Spreadsheets
    HDU 1069 Monkey and Banana
    codeforces 2B The least round way
    【机器学习】 通俗说拟合
    python-八皇后问题
    python-核心知识思维导图
    python-@property 属性
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4929102.html
Copyright © 2011-2022 走看看