• BZOJ5290: [Hnoi2018]道路


    【传送门:BZOJ3261


    简要题意:

      给出一棵2n-1个点的完全二叉树,非叶子节点为城市,叶子节点为乡村,城市一条边是公路,一条边是铁路,城市i向城市j连边必须满足i>j, 然后乡村有3个参数a[i],b[i],c[i],要求每一个城市选一条通向该城市的路进行翻修(也就是翻修n-1条道路)

      设乡村到首都城市1的路上,未翻修的公路条数是x,未翻修的铁路条数是y,每一个乡村的贡献是:c[i]*(a[i]+x)*(b[i]+y)要求选择一个翻修方案使得所有乡村贡献的总和最小


    题解:

      记忆化搜索(DP也可以)

      设f[i][j][k]为当前第i个点,未翻修j条公路,未翻修k条铁路的最小贡献

      因为是二叉树,每次往左右找,分别翻新公路和铁路就可以了


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int p=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){p=p*10+ch-'0';ch=getchar();}
        return p*f;
    }
    typedef long long LL;
    struct node
    {
        int lc,rc;
    }t[21000];
    LL f[21000][41][41];
    int a[41000],b[41000],c[41000];
    int n;
    LL dfs(int x,int d1,int d2)
    {
        if(x>=n) return LL(c[x])*LL(a[x]+d1)*LL(b[x]+d2);
        if(f[x][d1][d2]!=f[0][0][0]) return f[x][d1][d2];
        f[x][d1][d2]=min(dfs(t[x].lc,d1+1,d2)+dfs(t[x].rc,d1,d2),dfs(t[x].lc,d1,d2)+dfs(t[x].rc,d1,d2+1));
        return f[x][d1][d2];
    }
    int main()
    {
        n=read();
        for(int i=1;i<n;i++)
        {
            int lc=read(),rc=read();
            if(lc<0) lc=abs(lc)+n-1;
            if(rc<0) rc=abs(rc)+n-1;
            t[i].lc=lc;t[i].rc=rc;
        }
        for(int i=n;i<=2*n-1;i++) scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
        memset(f,63,sizeof(f));
        printf("%lld
    ",dfs(1,0,0));
        return 0;
    }

     

  • 相关阅读:
    [干货向]用Javascript获取页面元素的位置
    从 JavaScript 数组去重谈性能优化
    《悟透javascript》中的知识点
    深入理解javascript闭包
    深入理解Javascript之执行上下文(Execution Context)
    CSS Sprites的原理
    深入理解JavaScript定时机制
    防范sql注入式攻击的比较有见地的代码(PHP)
    PHP(authcode)加密解密
    预防数据库攻击
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8919509.html
Copyright © 2020-2023  润新知