• 5290: [Hnoi2018]道路


    5290: [Hnoi2018]道路

    链接

    分析:

      注意题目中说每个城市翻新一条连向它的公路或者铁路,所以两种情况分别转移一下即可。

      注意压一下空间,最后的叶子节点不要要访问,空间少了一半。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<cctype>
    #include<set>
    #include<vector>
    #include<queue>
    #include<map>
    #define fi(s) freopen(s,"r",stdin);
    #define fo(s) freopen(s,"w",stdout);
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 40001;
    int head[N], ls[N], rs[N], a[N], b[N], c[N], siz0[N], siz1[N], n;
    LL dp[20001][41][41];
    
    inline LL Calc(int u,int x,int y) { // 从根到u的路径上,表示翻新了x条公路,y条铁路 
        if (u >= n) return 1ll * c[u] * (siz0[u] - x + a[u]) * (siz1[u] - y + b[u]);
        return dp[u][x][y];
    }
    
    void dfs(int u) {
        if (u >= n) { return ;
    //        for (int i = 0; i <= siz0[u]; ++i) 
    //            for (int j = 0; j <= siz1[u]; ++j) 
    //                dp[u][i][j] = 1ll * c[u] * (siz0[u] - i + a[u]) * (siz1[u] - j + b[u]); // 表示翻新了i条公路,j条铁路 
    //        return ;
        }
        siz0[ls[u]] = siz0[u] + 1; siz1[ls[u]] = siz1[u]; dfs(ls[u]);
        siz0[rs[u]] = siz0[u]; siz1[rs[u]] = siz1[u] + 1; dfs(rs[u]);
    
        for (int i = 0; i <= siz0[u]; ++i)
            for (int j = 0; j <= siz1[u]; ++j) {
                dp[u][i][j] = 1e18;
                dp[u][i][j] = min(dp[u][i][j], Calc(ls[u], i + 1, j) + Calc(rs[u], i, j)); // 翻新公路
                dp[u][i][j] = min(dp[u][i][j], Calc(ls[u], i, j) + Calc(rs[u], i, j + 1)); // 翻新铁路
            }
    }
    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;
            ls[i] = u;
            rs[i] = v;
        }
        for (int i = 1; i <= n; ++i) 
            a[i + n - 1] = read(), b[i + n - 1] = read(), c[i + n - 1] = read();
        dfs(1);
        cout << dp[1][0][0];
        return 0;
    }
  • 相关阅读:
    CSS三大特性
    CSS选择器
    CSS(1)
    多媒体标签
    快捷键
    H5注意点(2)
    H5注意点(1)
    List详解
    求最大子串和以及其中一个子串(java)
    隧道项目
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10424511.html
Copyright © 2020-2023  润新知