1. 程式人生 > >hdu 5534 Partial Tree(完全揹包)

hdu 5534 Partial Tree(完全揹包)

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 nn nodes but lacks of n−1n−1edges. You want to complete this tree by adding n−1n−1 edges. There must be exactly one path between any two nodes after adding. As you know, there are nn−2nn−2 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)f(d), where ff is a predefined function and dd is the degree of this node. What's the maximum coolness of the completed tree?

Input

The first line contains an integer TT indicating the total number of test cases. 
Each test case starts with an integer nn in one line, 
then one line with n−1n−1 integers f(1),f(2),…,f(n−1)f(1),f(2),…,f(n−1). 

1≤T≤20151≤T≤2015 
2≤n≤20152≤n≤2015 
0≤f(i)≤100000≤f(i)≤10000 
There are at most 1010 test cases with n>100n>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

就是說有n個物品,每個物品體積分別是1,2,3...n      揹包容量為2(n-1)   又給出它們的價值   

求揹包中恰好用到n個物品,恰好將揹包裝滿能夠得到的最大價值。

一開始dp[物品數量][揹包體積   ]   n3複雜度  T了     

查閱部落格後   提前給n個物品都給一個  a[1]  就不用  考慮所用物品數量了   

注意到一個節點數為n的樹的度數和為2*n-2,所以問題就轉換為了把2*n-2個度分配給n個節點所能獲得的最大價值,而且每一個節點至少分到1個度。我們可以先每一個分一個度,然後把n-2個節點任意分配完。分配的時候因為已經分了1個度了,所以要把2~n-1的度看為1~n-1,然後做個完全揹包就行了。

 

#include <bits/stdc++.h>
using namespace std;
int main()
{
   int t;
   cin>>t;
   while(t--)
   {
       int a[2030],dp[2030],n;
       scanf("%d",&n);
       for(int i=1;i<n;i++)
       {
           scanf("%d",&a[i]);
       }
       for(int i=2;i<n;i++)
       {
           a[i]=a[i]-a[1];
       }
       for(int i=0;i<2030;i++)
       {
        dp[i]=-1000000;
       }
       dp[0]=0;
       int ans=0;
       ans+=a[1]*n;
       for(int j=2;j<=n-1;j++)
       {
           for(int i=1;i<=n-2;i++)
           {
               if(i+1>=j)
               dp[i]=max(dp[i],dp[i-j+1]+a[j]);
           }
       }
       printf("%d\n",ans+dp[n-2]);
   }
    return 0;
}