HDU 5534 完全背包

Partial Tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 823    Accepted Submission(s): 407


Problem Description
In mathematics, and more specifically in graph theory, a tree is an undirected graph in which any two nodes are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.

You find a partial tree on the way home. This tree has n nodes but lacks of n1 edges. You want to complete this tree by adding n1 edges. There must be exactly one path between any two nodes after adding. As you know, there are nn2 ways to complete this tree, and you want to make the completed tree as cool as possible. The coolness of a tree is the sum of coolness of its nodes. The coolness of a node is f(d), where f is a predefined function and d is the degree of this node. What's the maximum coolness of the completed tree?
 
Input
The first line contains an integer T indicating the total number of test cases.
Each test case starts with an integer n in one line,
then one line with n1 integers f(1),f(2),,f(n1).

1T2015
2n2015
0f(i)10000
There are at most 10 test cases with n>100.
 
Output
For each test case, please output the maximum coolness of the completed tree in one line.
 
Sample Input
2 3 2 1 4 5 1 4
 
Sample Output
5 19
 
题意:构造一颗最小生成树,但每个度数有个权值,使生成的权值最大。
 
题解:总共有2*n-2度数,如果从正面出发,就是直接完全背包,可能会使某些点被孤立,不能保证最小度数为1.所以先给每个点分配一个度数,直接n*f[1],因为最后肯定有度数大于1的点,先找出此度数和f[1]的差值(可负可正),相当于权值成了差值。最后还有n-2个度。这时候再用完全背包。即第一个for从2开始枚举到n-1度,(好比每个度数有无穷多个)第二个for枚举n-2个度。
状态转移方程:    dp[j]  = max(dp[j],dp[j-i+1]+f[i]).       为什么是j-i+1不是j-i呢,因为j是1到n-2中度,j-1相当于把那个1分配给一个度数已经为1的点,度数成了2,所以+f[2].
 
 
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 2020;
const int inf = 0x3f3f3f3f;
int f[maxn];
int dp[maxn];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        int ans = 0;
        scanf("%d",&n);
        for(int i = 1; i<n; i++) scanf("%d",&f[i]);
        ans = n*f[1];
        for(int i = n-1; i>1; i--) f[i] -= f[1];
        for(int i = 1; i<=n-2; i++)
            dp[i] = -inf;
            dp[0] = 0;
        for(int i = 2; i <= n-1; i++)   //因为1度已定,所以从2枚举度数
            for(int j = 1; j <= n-2; j++) 
                if(j>=i-1) dp[j] = max(dp[j],dp[j-i+1]+f[i]);
        printf("%d
",ans+dp[n-2]);
    }
    return 0;
}
 
 
原文地址:https://www.cnblogs.com/littlepear/p/5671054.html