首页 > 其他 > 详细

[HNOI/AHOI2018]道路

时间:2019-08-14 11:22:11      阅读:79      评论:0      收藏:0      [点我收藏+]

*不好确定的可以加进状态

方程:

叶节点(边界)

$f[u][i][j] = c[u]*(a[u]+i)*(b[u]+j);$

非叶节点:

$f[u][i][j] = min(f[ls][i+1][j]+f[rs][i][j],f[ls][i][j]+f[rs][i][j+1]);$

但这题更为重要的是空间优化

技术分享图片

对于每一层,我们可以给他们的儿子分别附一个编号,同一层编号相同。

因为$u$只由他的儿子转移来,并且他的儿子也只会转移给$u$,所以儿子转移后就没用了,可以让后来的直接覆盖掉儿子

具体实现如下

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std; 

template <typename T> void in(T &x) {
    x = 0; T f = 1; char ch = getchar();
    while(!isdigit(ch)) {if(ch == -) f = -1; ch = getchar();}
    while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
    x *= f;
}

template <typename T> void out(T x) {
    if(x < 0) x = -x , putchar(-);
    if(x > 9) out(x/10);
    putchar(x%10 + 48);
}
//-------------------------------------------------------

const int N = 20001,k = 19;

int n;
int son[N][2];
int a[N],b[N],c[N];
ll f[80][20][20];

void dfs(int u,int id) {
    int i,j;
    if(u < 0) {
        u = -u;
        for(i = 0;i <= k; ++i) {
            for(j = 0;j <= k; ++j) {
                f[id][i][j] = 1ll*c[u]*(a[u]+i)*(b[u]+j);
            }
        }
        return;
    }
    dfs(son[u][0],id+1); dfs(son[u][1],id+2);
    for(i = 0;i <= k; ++i) {
        for(j = 0;j <= k; ++j) {
            f[id][i][j] = min (
                f[id+1][i+1][j]+f[id+2][i][j],
                f[id+1][i][j]+f[id+2][i][j+1]
            );
        }
    }
}

int main() {
    //freopen("0.in","r",stdin); 
    int i;
    in(n);
    for(i = 1;i < n; ++i) in(son[i][0]),in(son[i][1]);
    for(i = 1;i <= n; ++i) in(a[i]),in(b[i]),in(c[i]);
    dfs(1,1);
    out(f[1][0][0]);
    return 0;
}

 

[HNOI/AHOI2018]道路

原文:https://www.cnblogs.com/mzg1805/p/11350245.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!