题解 P1270 【“访问”美术馆】

· · 题解

一个有趣的树形动规。。。。

注意可以不把一个展厅的画取完,害的我找了半天的错。。

可以在每个叶节点(非展厅)把剩余时间与偷的画的数量记录下来

附上代码:

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
struct qe
{
    int is,t,fa,l[3],r;
}map[1000];
int n=1,ti;
int qw[103][603];
int we(int a,int b)
{
    if(b>a) return a;
    return b;
}
int work(int a,int time)
{
    if(qw[a][time]!=-1) return qw[a][time];    
    if(map[a].is!=0)
    if(map[a].t<=time) 
    {qw[a][time]=we(map[a].is,(time-map[a].t)/5);
    return qw[a][time];
    }
    else 
    {qw[a][time]=0;
    return 0;
    }    
    if(time-map[a].t<=0) return 0;
    time-=map[a].t;
    int l=map[a].l[1],r=map[a].l[2];
    int max=0;
    for(int i=0;i<=time;i++) 
    {
        int t1,t2;
        t1=work(l,time-i);
        t2=work(r,i);
        if(t1+t2>max) max=t1+t2;    
    }
    qw[a][time+map[a].t]=max;
    return max;
}
int main()
{
    int i,j,k;
    scanf("%d",&ti);
    for(i=1;;i++)
    {
        scanf("%d%d",&map[i].t,&map[i].is);
        map[i].r=1;
        if(i!=1)
        {
            for(j=i-1;j>=1;j--)
            {
                if(map[j].is==0&&map[j].r!=3)
                {
                    map[i].fa=j;
                    map[j].l[map[j].r]=i;
                    map[j].r++;
                    break;
                }
            }
        }
        int p=1;
        for(j=1;j<=i;j++) if(map[j].r!=3&&map[j].is==0) p=0;
        if(p==1) break;
    }
    n=i;
    for(i=1;i<=n;i++) 
    {
        map[i].t*=2;
    }
    for(i=1;i<=n;i++)for(j=0;j<=ti;j++) qw[i][j]=-1;
    int ans;
    ans=work(1,ti);    
    printf("%d",ans);    
    return 0;
}