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 n nodes but lacks of n−1 edges. You want to complete this tree by adding n−1 edges. There must be exactly one path between any two nodes after adding. As you know, there are nn−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), 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 n−1 integers f(1),f(2),…,f(n−1). 1≤T≤2015 2≤n≤2015 0≤f(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
題解:
因為n-1條邊要連線所有的點,所以我們可以先讓每條邊與一個點一對一連線,那麼我們得到(n-1)個度為一的點,剩下一個度為0的是根節點,然後我們讓一條邊與根節點相連,那麼現在n個點的度都為一,因為所有邊共產生2*(n-1)度所以剩下(n-2)度,所以問題轉化成把(n-2)個度分給n個點,使得結果的f(d)和最大。
這明顯是一個完全揹包問題了。可以把度數想成weight,f(d)想成value,(n-2)為揹包最大容量,那麼這就是一個基礎的完全揹包放東西模板。
注意這裡d 和 f(d)都為原值與1和f(1)的差值,也因此會有負數。
程式碼:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 2020;
const long long INF = 0x3f3f3f3f3f3f3f3f;
struct D{
long long f,d;
}board[MAXN];
long long dp[MAXN*2];
int main(){
int T,N;
scanf("%d",&T);
while(T--){
memset(dp,-INF,sizeof dp);
scanf("%d",&N);
scanf("%lld",&board[1].f);
board[1].d = 1;
for(int i=2 ; i<N ; ++i){
long long t;
scanf("%lld",&t);
board[i].f = t - board[1].f;
board[i].d = i-1;
}
dp[0] = 0;
long long re = N*board[1].f;
for(int i=2 ; i<N ; ++i){
for(int j=board[i].d ; j<=N-2 ; ++j){
if(dp[j-board[i].d] != -INF)dp[j] = max(dp[j],dp[j-board[i].d]+board[i].f);
}
}
printf("%lld\n",re+dp[N-2]);
}
return 0;
}