HDU 5534(Partial Tree-背包)

来源:互联网 发布:做网络的主人教案 编辑:程序博客网 时间:2024/05/16 02:04

给一颗N个节点的树,f(i)表示度数为i的节点的点权,问这棵树最大点权

背包
显然,任意一种 能使总度数=2*(n-1)且每个节点度数至少1的方案都存在。

由于规定刚好N个节点,直接背包O(n3)

假设每个节点度数=1 ,剩下节点度数之和m=n2
可以任意分配剩下n-2个度数,完全背包这样是O(n2)

#include <iostream>#include <cmath>#include <algorithm>#include <cstdio>#include <cstring>#include <string>#include <vector>#include <map>#include <functional>#include <cstdlib>#include <queue>#include <stack>using namespace std;typedef long long ll;#define For(i,n) for(int i=1;i<=n;i++)#define Rep(i,n) for(int i=0;i<n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define MAXN (3000)int T;int a[MAXN],n;ll f[MAXN][MAXN];int main() {    int T; cin>>T;    while(T--) {        cin>>n;        For(i,n-1) scanf("%d",&a[i]);        ll ans=a[1]*n;        Fork(i,2,n-1) a[i]-=a[1];        For(i,n-2) a[i]=a[i+1];        //For(i,n-2) cout<<a[i]<<endl;        int m=n-2;        For(i,m) {            For(j,n-2) {                if (j==1)                 {                    f[i][j]=a[1]*i;                    continue;                }                if (j>1) f[i][j]=f[i][j-1];                if (i==j) f[i][j]=max(f[i][j],(ll)a[j]);                if (i-j>0) f[i][j]=max(f[i][j],f[i-j][j]+ a[j]);            }        }        /*        For(i,m) {            For(j,n-2) {                cout<<i<<':'<<j<<':'<<f[i][j]<<endl;            }        }*/        cout<<ans+f[m][n-2]<<endl;    }    return 0;}
0 0
原创粉丝点击