# BZOJ 1564: [NOI2009]二叉查找树

#include<cstdio>
#include<algorithm>
using namespace std;
int n,K,F[105][105][105],b[105],Sum[105];
struct node{
int sum,id,val;
}a[105];
bool cmp(node a,node b){
return a.sum<b.sum;
}
int main(){
scanf("%d%d",&n,&K);
for (int i=1; i<=n; i++) scanf("%d",&a[i].sum);
for (int i=1; i<=n; i++) scanf("%d",&a[i].id);
for (int i=1; i<=n; i++) b[i]=a[i].id;
for (int i=1; i<=n; i++) scanf("%d",&a[i].val);
sort(a+1,a+n+1,cmp);
sort(b+1,b+n+1);
int N=unique(b+1,b+n+1)-b-1;
for (int i=1; i<=n; i++) a[i].id=lower_bound(b+1,b+N,a[i].id)-b;
for (int i=1; i<=n; i++)
for (int j=i; j<=n; j++)
for (int k=0; k<=N; k++)
F[i][j][k]=1e9;
for (int i=1; i<=n; i++) Sum[i]=Sum[i-1]+a[i].val;
for (int i=1; i<=n; i++)
for (int k=0; k<=N; k++){
F[i][i][k]=a[i].val;
if (k>a[i].id) F[i][i][k]+=K;
}
for (int len=1; len<n; len++)
for (int i=1; i<n; i++){
int j=i+len;
if (j>n) break;
for (int lim=0; lim<=N; lim++)
for (int k=i; k<=j; k++){
F[i][j][lim]=min(F[i][j][lim],F[i][k-1][lim]+F[k+1][j][lim]+K+Sum[j]-Sum[i-1]);
if (lim<=a[k].id) F[i][j][lim]=min(F[i][j][lim],F[i][k-1][a[k].id]+F[k+1][j][a[k].id]+Sum[j]-Sum[i-1]);
}
}
int ans=1e9;
for (int i=0; i<=N; i++) ans=min(ans,F[1][n][i]);
printf("%d\n",ans);
return 0;
}


posted @ 2018-11-07 19:21  ~Silent  阅读(125)  评论(0编辑  收藏  举报
Live2D