zoukankan      html  css  js  c++  java
  • [bzoj5290][Hnoi2018]道路【树形dp】

    【题目链接】
      https://www.lydsy.com/JudgeOnline/problem.php?id=5290
      https://www.luogu.org/problemnew/show/P4438
    【题解】
      记f[i][j][k]表示现在在i号点从根节点到这个点经过了j条未被修缮的公路和k条未被修缮的铁路的答案。
      于是有:

    f[i][j][k]=min(f[son[0]][j+1][k]+f[son[1]][j][k],f[son[0]][j][k]+f[son[1]][j][k+1])

      son[0]为公路连接的儿子,son[1]为铁路连接的儿子。
      叶子节点的答案直接计算即可,注意在用到的时候再算,否则可能会爆空间。
      最后的答案为f[1][0][0]
      时间复杂度:O(ND2)  D为深度。
      

    # include <bits/stdc++.h>
    # define    N       20010
    # define    T       41
    # define    ll      long long
    # define    inf     0x3f3f3f3f
    using namespace std;
    int read(){
        int tmp=0, fh=1; char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
        while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
        return tmp*fh;
    }
    int son[N][2],n;
    ll f[N][T][T],v[N][3];
    ll calc(int x, int i, int j){
        return v[x-n+1][2]*(v[x-n+1][0]+i)*(v[x-n+1][1]+j);
    }
    void dfs(int x, int num0, int num1){
        if (x>=n) return;
        else {
            dfs(son[x][0],num0+1,num1);
            dfs(son[x][1],num0,num1+1);
            for (int i=0; i<=num0; i++)
                for (int j=0; j<=num1; j++){
                    ll tmp00, tmp01, tmp10, tmp11;
                    if (son[x][0]>=n)
                        tmp00=calc(son[x][0],i,j),tmp01=calc(son[x][0],i+1,j);
                        else tmp00=f[son[x][0]][i][j],tmp01=f[son[x][0]][i+1][j];
                    if (son[x][1]>=n)
                        tmp10=calc(son[x][1],i,j),tmp11=calc(son[x][1],i,j+1);
                        else tmp10=f[son[x][1]][i][j],tmp11=f[son[x][1]][i][j+1];
                    f[x][i][j]=min(tmp00+tmp11,tmp01+tmp10);
                }
        }
    }
    int main(){
        n=read();
        for (int i=1; i<n; i++){
            int u=read(), v=read();
            if (u<0) u=-u+(n-1);
            if (v<0) v=-v+(n-1);
            son[i][0]=u;
            son[i][1]=v;
        }
        for (int i=1; i<=n; i++){
            v[i][0]=read();
            v[i][1]=read();
            v[i][2]=read();
        }
        memset(f,inf,sizeof(f));
        dfs(1,0,0);
        printf("%lld
    ",f[1][0][0]);
        return 0;
    }
    
  • 相关阅读:
    Eclipse 下找不到或无法加载主类的解决办法
    程序 查看 jvm版本
    BaseAdapter优化深入分析
    android自定义UI模板图文详解
    android注解使用详解(图文)
    Unity随机Prefab,自动前往某点处理
    三分钟学会缓存工具DiskLruCache
    怎样判断一个股权众筹项目是否靠谱?
    P2P借款的几种情况
    android开发必备日志打印工具类
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9135951.html
Copyright © 2011-2022 走看看