URAL 1018

来源:互联网 发布:电商和微商的区别 知乎 编辑:程序博客网 时间:2024/05/16 09:35

题目大意:给一棵共有N个枝条的二叉苹果树,每个枝上有apple[i][j]个苹果,求保留Q个枝条时,能够留下的最大苹果数。

Time Limit:1000MS     Memory Limit:16384KB     64bit IO Format:%I64d & %I64u

数据规模:2<=N<=100,1<=Q<=N-1,0<applle[i][j]<=30000。

理论基础:无。

题目分析:树dp。我们首先将所有的苹果转移到朝向叶子节点方向的节点。再添加一个虚拟的枝条,由虚拟根节点0指向根节点,这样方便后续的dp操作。

用dp[i][j]表示以i为根节点的子树,保留j个枝条时所能留下的最大苹果数。tree[i]表示编号为i的节点。

那么状态转移方程dp[i][j]=max(dp[tree[i].l][j-k]+dp[tree[i].r][k-1],(0<=k<j))+tree[i].value。

节点中存放的数据有,左儿子,右儿子,和苹果的数值。

采用记忆化搜索dp即可。答案即为:dp[1][++Q]的值。

代码如下:

#include<iostream>#include<cstring>#include<string>#include<cstdlib>#include<cstdio>#include<cmath>#include<algorithm>#include<queue>#include<ctime>#include<vector>using namespace std;typedef double db;#define DBG 1#define maa (1<<31)#define mii ((1<<31)-1)#define ast(b) if(DBG && !(b)) { printf("%d!!|\n", __LINE__); while(1) getchar(); }  //调试#define dout DBG && cout << __LINE__ << ">>| "#define pr(x) #x"=" << (x) << " | "#define mk(x) DBG && cout << __LINE__ << "**| "#x << endl#define pra(arr, a, b)  if(DBG) {\    dout<<#arr"[] |" <<endl; \    for(int i=a,i_b=b;i<=i_b;i++) cout<<"["<<i<<"]="<<arr[i]<<" |"<<((i-(a)+1)%8?" ":"\n"); \    if((b-a+1)%8) puts("");\}template<class T> inline bool updateMin(T& a, T b) { return a>b? a=b, true: false; }template<class T> inline bool updateMax(T& a, T b) { return a<b? a=b, true: false; }typedef long long LL;typedef long unsigned int LU;typedef long long unsigned int LLU;#define N 105#define Q 105struct treeNode{    int lc,rc,value;}tree[N];int dp[N][Q],apple[N][N],n,q;bool visit[N];void maketree(int root){    visit[root]=true;    for(int i=1;i<=n;i++)    {        if(!visit[i]&&apple[root][i]!=-1)        {            if(tree[root].lc==0)tree[root].lc=i;            else tree[root].rc=i;            tree[i].value=apple[root][i];            maketree(i);        }    }}void init(){    memset(tree,0,sizeof tree);    memset(dp,-1,sizeof dp);    memset(visit,false,sizeof visit);    memset(apple,-1,sizeof apple);}int treedp(int root,int pdt){    if(root==0||pdt==0)return 0;    if(dp[root][pdt]!=-1)return dp[root][pdt];    int maxn=maa,lans,rans;    for(int i=0;i<pdt;i++)    {        lans=treedp(tree[root].lc,i);        rans=treedp(tree[root].rc,pdt-i-1);        if(lans+rans>maxn)maxn=lans+rans;    }    return dp[root][pdt]=maxn+tree[root].value;}int main(){    init();    scanf("%d%d",&n,&q);    for(int i=1;i<n;i++)    {        int l,r,v;        scanf("%d%d%d",&l,&r,&v);        apple[l][r]=apple[r][l]=v;    }    maketree(1);    printf("%d\n",treedp(1,++q));return 0;}

其中,root为0的时候或者pdt为0的时候,无论怎样都不会留下苹果。

by:Jsun_moon http://blog.csdn.net/jsun_moon


原创粉丝点击