AHOI/HNOI2018道路



找性质,倒推

我简直是傻逼,题都没看完,然后半天做不起

一道简单的树形DP,但是要卡空间

(f[i][u][v])从根到i,选了u条公路v条铁路的最小代价,显然答案是(f[1][0][0])

从叶子节点倒推

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
const int N=20004;
int n,lc[N],rc[N],f[88][44][44],top,st[88],a[N<<1],b[N<<1],c[N<<1];
inline void dfs(int x){
	st[++top]=x;
	memset(f[top],0x3f,sizeof(f[top]));
	if(x>=n){
		for(int u=0;u<=40;u++)
			for(int v=0;v+u<=40;v++)
				f[top][u][v]=c[x]*(a[x]+u)*(b[x]+v);
		return;
	}
	dfs(lc[x]);dfs(rc[x]);
	for(int u=0;u<=40;u++)
		for(int v=0;v+u<=40;v++)
			f[top-2][u][v]=min(f[top-2][u][v],min(f[top-1][u+1][v]+f[top][u][v],f[top-1][u][v]+f[top][u][v+1]));
	if(rc[x])top--;
	if(lc[x])top--;
}
signed main(){
	n=read();
	for(int i=1;i<n;i++){
		lc[i]=read();rc[i]=read();
		if(lc[i]<0)lc[i]=n-1-lc[i];
		if(rc[i]<0)rc[i]=n-1-rc[i];
	}
	for(int i=n;i<(n<<1);i++){
		a[i]=read();b[i]=read();c[i]=read();
	}
	dfs(1);
	cout<<f[1][0][0];
	return (0-0);
}
原文地址:https://www.cnblogs.com/aurora2004/p/12584002.html