HDU-5534 完全揹包DP
阿新 • • 發佈:2020-11-30
HDU-5534
題目大意
t組資料
讓你構造一個\(n\)個節點的樹,每個節點的權值為\(f(i)\),\(i\)為該點的入度,要求該樹的權值和最大,輸出這個值
\(1≤T≤2015\)
\(2≤n≤2015\)
\(0≤f(i)≤10000\)
思路
首先我們知道一個性質,n個節點的樹入度和為2n-2,且每個點入度至少為1,那麼還有n-2個入度是我們可以自由分配的。
於是我們可以預賦值dp[0]=n*f(1),dp[其他]=\(-INF\),因為有可能f(i)的值為負數
還有要注意的一點,就是如果一個點被額外分配了2個度,那麼他的值是從f(1)變為了f(3),因此想表示加k度時,應用f(k)-f(1)表示。
然後就變成了完全揹包,我們可以壓一維空間
Code
#include<string> #include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; #define LL long long #define MOD 998244353 #define PI 3.1415926535898 #define INF 0x3f3f3f3f #define MAXN 2050 const double EPS = 1e-8; LL read() { LL x = 0, w = 1; char ch = 0; while (ch < '0' || ch>'9') { if (ch == '-') { w = -1; } ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return w * x; } int t, f[MAXN], n, dp[MAXN]; int main() { t = read(); while (t--) { memset(f, 0, sizeof(f)); memset(dp, -INF, sizeof(dp)); n = read(); for (register int i = 1; i < n; i++) { f[i] = read(); } dp[0] = n * f[1]; for (register int i = 2; i < n; i++) { for (register int j = i - 1; j <= n - 2; j++) { dp[j] = max(dp[j], dp[j - i + 1] + f[i] - f[1]); } } cout << dp[n - 2] << endl; } return 0; }