您的位置:首页 > 其它

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

2013-09-14 15:43 197 查看
题目来源:http://wikioi.com/problem/1163/

分析:

树状动态规划。

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

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#define maxn 301
#define maxt 601
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  oi 动态规划 树结构