分享优化思路
查看原帖
分享优化思路
218172
BiaxialRay楼主2024/8/7 17:46

核心优化思路是减少循环次数,从能偷到子树内最近的画开始计算,能偷完子树内所有画便结束循环
结构体Tree中的dp[i]表示在该子树内,i时间内,能偷到的画的最多数量
以下为代码,关键变量已注释
通过#5测试点花费的时间:
开启O2优化:36ms
不开启O2优化:116ms

#include<cstdio>
#include<cstring>
using namespace std;
const int Maxn = 10050;
int temp,n;

int max(int x,int y){
    return x > y ? x : y;
}
int min(int x,int y){
    return x < y ? x : y;
}

struct Tree{
    Tree *left = NULL;
    Tree *right = NULL;
    int dp[Maxn];
    int num = 0; //画的数量
    int len = 0; //往返走廊的时间
    int kind = 0; //判断是否为根节点
    int max_t = 0; //偷完子树内所有画所需时间
    int min_t = 0; //仅往返子树内最近展览室的时间
    int tot = 0; //从出口到该位置仅往返时间
    Tree(){
        memset(dp,0,sizeof(dp));
    }
}tree[205];

Tree* scan(){
    int t1,t2;
    Tree* t = &tree[temp];
    scanf("%d %d",&t1,&t2);
    t->len = t1 * 2;
    if (t2 == 0){
        ++temp;t->left = scan();t->left->tot = t->tot + t->len;
        ++temp;t->right = scan();t->right->tot = t->tot + t->len;
        t->kind = 1;
    }else{
        t->num = t2;
    }
    return t;
}

void f(Tree *t){
    if(t->kind){ 
        int i,j,x,y;
        f(t->left);
        f(t->right);
        t->max_t = t->left->max_t + t->len + t->right->max_t;
        if(t->max_t > n - t->tot){
            t->max_t = n - t->tot;
        }
        x = t->left->min_t;
        y = t->right->min_t;
        t->min_t = min(x,y) + t->len;
        for(i = t->min_t + 5;i <= t->max_t;++i){
            for(j = max(0,i-t->len-t->right->max_t);j <= i - t->len && j <= t->left->max_t;++j){
                t->dp[i] = max(t->dp[i],t->left->dp[j] + t->right->dp[i-t->len-j]);
            }
        }
    }else{
        t->max_t = 5*t->num + t->len;
        t->min_t = t->len;
        int k = 5 + t->len,i,j;
        for(i = 1;i <= t->num;++i){
            for(j = 0;j < 5;++j){
                t->dp[k] = i;
                ++k;
            }
        }
    }
}

int main(){
    scanf("%d",&n);
    scan();
    f(&tree[0]);
    if(tree[0].max_t < n - 1){
        printf("%d",tree[0].dp[tree[0].max_t]);
    }else{
        printf("%d",tree[0].dp[n-1]);
    }
    scanf("%d",&n);
    return 0;
}
2024/8/7 17:46
加载中...