【树形DP】wikioi 1163 访问艺术馆

来源:互联网 发布:ftp控制协议端口 编辑:程序博客网 时间:2024/04/30 15:12

题目来源:http://wikioi.com/problem/1163/

分析:

树状动态规划。

用树存储艺术馆内的情况,然后从根到叶递归求解。对于每个节点,将可用时间分给他的左右儿子,枚举所有分法,取最大值。最后输出根节点的数值即可。

代码:

#include<cstdio>#include<iostream>#include<cstring>#define maxn 301#define maxt 601using namespace std;struct node{int t,ls,rs,v;}te[maxn];     //储存树的信息 int a[maxn][2],f[maxn][maxt],m=0,i,ti;void build(int r)   //递归建树 { te[r].t=2*a[r][0];te[r].v=a[r][1];if (a[r][1]!=0){te[r].ls=te[r].rs=-1;return;}te[r].ls=++m;build(m);te[r].rs=++m;build(m);}int dfs(int r,int i){if (f[r][i]!=-1) return f[r][i];   //如果已有值,直接返回 if (i==0) return f[r][i]=0;        //时间没了,返回     if (te[r].ls==-1)                                        {    if (te[r].v*5<i-te[r].t) return te[r].v; //能拿完     else return (i-te[r].t)/5;               //不能拿完     }    int lt,rt;    for (lt=0;lt<=i-te[r].t;lt++)      //枚举不同分法      {     rt=i-te[r].t-lt;     int s1=dfs(te[r].ls,lt);     int s2=dfs(te[r].rs,rt);     f[r][i]=max(f[r][i],s1+s2);     }    return f[r][i];}int main(){memset(f,-1,sizeof(f));scanf("%d",&ti);while (scanf("%d%d",&a[i][0],&a[i][1])!=EOF) i++;build(m);printf("%d",dfs(0,ti));return 0;}


原创粉丝点击