Bzoj5290: [Hnoi2018]道路
BZOJ5290: [Hnoi2018]道路
题解
为什么是pj树型dp。。。
感觉考场上紧张的话写不出很正常啊。。
设置一个状态
\(f[i][x][y]\)表示,第i个节点,往上还有x条路和y条路没有修。
f[i][x][y]=min(f[左儿子][x+1][y]+f[右儿子][x][y],f[左儿子][x][y]+f[右儿子][x][y+1]);
含义是分别是修右儿子,修左儿子。
然后写完了。。。注意的是,卡空间。
Code
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=4e4+5;
int n,a[N],b[N],c[N];
ll f[N][41][41];
int ch[N][2];
ll read(){
ll x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
void dfs(ll x,ll left,ll right){
if(x>=n){
for(ll i=0;i<=left;i++)
for(ll j=0;j<=right;j++)
f[x][i][j]=1ll*c[x]*(a[x]+i)*(b[x]+j);
return ;
}
dfs(ch[x][0],left+1,right+1);dfs(ch[x][1],left+1,right+1);
for(ll i=0;i<=left;i++){
for(ll j=0;j<=right;j++){
ll v1=f[ch[x][0]][i+1][j]+f[ch[x][1]][i][j];
ll v2=f[ch[x][0]][i][j]+f[ch[x][1]][i][j+1];
f[x][i][j]=min(v1,v2);
}
}
}
int main(){
n=read();
for(ll i=1;i<n;i++){
ll x=read(),y=read();
if(x<0)x=-x+n-1;if(y<0)y=-y+n-1;
ch[i][0]=x;ch[i][1]=y;
}
for(ll i=n;i<=2*n-1;i++){
a[i]=read();b[i]=read();c[i]=read();
}
dfs(1,0,0);
cout<<f[1][0][0]<<endl;
return 0;
}