bzoj 5290: [Hnoi2018]道路

Description

Solution

PJDP毁青春
注意到性质:到根的道路不超过 (40)
所以我们只关系一个点上面的道路的情况就行了
(f[x][i][j]) 表示一个点 (x) ,上面有 (i) 条公路没修,(j) 条铁路没修的最小代价
(f[x][i][j]=min(f[ls][i+1][j]+f[rs][i][j],f[ls][i][j]+f[rs][i][j+1]))

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=40010;
int n,ls[N],rs[N],b[N][2];
ll A[N],B[N],C[N],f[20010][45][45];
int xl[N],yl[N],tn;
inline void DFS(int x,int X,int Y){
  xl[x]=X;yl[x]=Y;
  if(x>=n)return ;
  DFS(ls[x],X+1,Y);
  DFS(rs[x],X,Y+1);
}
inline ll F(int x,int i,int j){
  if(x<n)return f[x][i][j];
  return C[x]*(A[x]+i)*(B[x]+j);
}
inline void dfs(int x){
  if(x>=n)return ;
  dfs(ls[x]);dfs(rs[x]);
  for(int i=0;i<=xl[x];i++)
    for(int j=0;j<=yl[x];j++)
      f[x][i][j]=min(F(ls[x],i+1,j)+F(rs[x],i,j),F(ls[x],i,j)+F(rs[x],i,j+1));
}
int main(){
  scanf("%d",&n);tn=n+n-1;
  for(int i=1;i<n;i++){
    scanf("%d%d",&b[i][0],&b[i][1]);
    if(b[i][0]<0)b[i][0]=-b[i][0]+n-1;
    if(b[i][1]<0)b[i][1]=-b[i][1]+n-1;
    ls[i]=b[i][0];rs[i]=b[i][1];
  }
  for(int i=1;i<=n;i++)cin>>A[i+n-1]>>B[i+n-1]>>C[i+n-1];
  DFS(1,0,0);
  memset(f,127/3,sizeof(f));
  dfs(1);
  cout<<f[1][0][0]<<endl;
  return 0;
}

原文地址:https://www.cnblogs.com/Yuzao/p/8856773.html