Codevs No.1163 访问艺术馆

时间:2022-07-30 10:28:06

2016-05-31 20:48:47

题目链接: 访问艺术馆 (Codevs No.1163)

题目大意:

  一个贼要在一个二叉树结构的艺术馆中偷画,画都处于叶子节点处,偷画和经过走廊都需要时间,求在限定时间内可以偷到最大数量

解法:

  树状DP (记忆化搜索实现)

  DP[i][j]表示到达i节点时还有j的时间来移动可以偷到的最大数量

  状态转移:

    对于叶子节点,直接按时间剩余返回最大偷画数量  

    对于非叶子节点,最大值可能来自Lson一边,也可能只来自Rson一边,还有可能是Lson,Rson按某种方式分配时间得来

  话说这题按照深度优先顺序给树有点坑啊

需要注意的地方:

  1.偷画是要有来有回的,所以要把走廊的长度*2

  2.第一条走廊并不满足二叉结构,可以直接手动去掉

 //访问艺术馆 (Codevs No.1163)
//树状DP
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn=;
const int maxt=;
int DP[maxn][maxt];
int T;
int Index=;
int val[maxn];
int lson[maxn];
int rson[maxn];
int lenlson[maxn];
int lenrson[maxn];
void Build(int now)
{
int len,num;
scanf("%d %d",&len,&num);
lson[now]=++Index;
lenlson[now]=len*;
if(num==)Build(lson[now]);
else val[lson[now]]=num;
scanf("%d %d",&len,&num);
rson[now]=++Index;
lenrson[now]=len*;
if(num==)Build(rson[now]);
else val[rson[now]]=num;
return ;
}
int DFS(int x,int time)
{
if(time<)return -;
if(DP[x][time]>-)return DP[x][time];
if(lson[x]==&&rson[x]==)
{
for(int i=val[x];i>=;i--)
{
if(time-i*>=)return DP[x][time]=i;
}
}
DP[x][time]=;
DP[x][time]=max(DP[x][time],DFS(lson[x],time-lenlson[x]));
DP[x][time]=max(DP[x][time],DFS(rson[x],time-lenrson[x]));
for(int i=lenlson[x];time-i>=lenrson[x];i++)
{
DP[x][time]=max(DP[x][time],DFS(lson[x],i-lenlson[x])+DFS(rson[x],time-i-lenrson[x]));
}
return DP[x][time];
}
int main()
{
int x,y;
scanf("%d",&T);
scanf("%d %d",&x,&y);
if(y==)
{
Build();
}
memset(DP,-,sizeof(DP));
DFS(,T-x*-);
if(T-x*->=)printf("%d",DP[][T-x*-]);
else printf("");
return ;
}