1. 程式人生 > >bzoj5290:[Hnoi2018]道路

bzoj5290:[Hnoi2018]道路

tchar spa iostream pro read 簡單的 noi gis struct

傳送門

作為\(HNOI2018\)最簡單的題,這個題確實不算難

雖然我一開始也沒想出滿分

看了眼題解,考慮到了倒推,這題差不多就沒了

當走到葉子節點的時候考慮一下選了多少條公路翻修和多少條鐵路翻修

對於非葉子節點就枚舉翻修哪條邊,轉移就好了

一個小插曲:

本來寫的記搜,由於看錯題了,以為自己寫錯了,全刪了,才學的題解的\(dp\)寫法

代碼:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void read(int &x)
{
    char ch;bool ok;
    for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
    for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
}
#define rg register
const int maxn=4e4+10;
int n,l[maxn],r[maxn],cnt;
long long f[maxn][40][40];
struct oo{int a,b,c;}d[maxn];
void dfs(int x,int a,int b)
{
    if(!l[x]&&!r[x]){
        for(rg int i=0;i<=a;i++)
            for(rg int j=0;j<=b;j++)
                f[x][i][j]=1ll*d[x].c*(d[x].a+i)*(d[x].b+j);
        return ;
    }
    dfs(l[x],a+1,b),dfs(r[x],a,b+1);
    for(rg int i=0;i<=a;i++)
        for(rg int j=0;j<=b;j++)
            f[x][i][j]=min(f[l[x]][i+1][j]+f[r[x]][i][j],f[l[x]][i][j]+f[r[x]][i][j+1]);
}
int main()
{
    read(n);
    for(rg int i=1,x,y;i<n;i++){
        read(x),read(y);
        if(x>0)l[i]=x;else l[i]=n-x;
        if(y>0)r[i]=y;else r[i]=n-y;
    }
    for(rg int i=1;i<=n;i++)read(d[i+n].a),read(d[i+n].b),read(d[i+n].c);
    dfs(1,0,0);
    printf("%lld\n",f[1][0][0]);
}

bzoj5290:[Hnoi2018]道路