dp[i][j][k]表示[i,j],子树权值>=k的答案。
注意因为考虑每一层的贡献,因此这个dp和深度无关。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 85 #define inf 1000000007 using namespace std; int n,k,a[maxv],b[maxv],dp[maxv][maxv][maxv],sum[maxv]; struct pnt { int w,val,p; friend bool operator < (const pnt &x,const pnt &y) { return x.w<y.w; } }p[maxv]; int get_dp(int l,int r,int w) { if (dp[l][r][w]) return dp[l][r][w]; if (l==r) return sum[l]-sum[l-1]+(p[l].val<w)*k; if (l>r) return 0; dp[l][r][w]=inf; for (int i=l;i<=r;i++) { if (p[i].val>=w) dp[l][r][w]=min(dp[l][r][w],get_dp(l,i-1,p[i].val)+get_dp(i+1,r,p[i].val)+(sum[r]-sum[l-1])); dp[l][r][w]=min(dp[l][r][w],get_dp(l,i-1,w)+get_dp(i+1,r,w)+(sum[r]-sum[l-1])+k); } return dp[l][r][w]; } int main() { scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) scanf("%d",&p[i].w); for (int i=1;i<=n;i++) {scanf("%d",&a[i]);b[i]=a[i];} for (int i=1;i<=n;i++) scanf("%d",&p[i].p); sort(b+1,b+n+1); for (int i=1;i<=n;i++) p[i].val=lower_bound(b+1,b+n+1,a[i])-b; sort(p+1,p+n+1); for (int i=1;i<=n;i++) sum[i]=sum[i-1]+p[i].p; int mn=inf; for (int i=0;i<=n;i++) mn=min(mn,get_dp(1,n,i)); printf("%d\n",mn); return 0; }