# 【BZOJ1564】【NOI2009】二叉查找树（动态规划）

BZOJ

## 题解

$f[i][j][k]=min(f[i][p-1][n]+f[p+1][j][m]+\sum_{l\in[i,j]}s[l]+[v[i]==k]·K)$

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 75
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Node{int v,key,s;}t[MAX];
bool operator<(Node a,Node b){return a.v<b.v;}
int S[MAX],n,K;
int f[MAX][MAX][MAX];
int main()
{
sort(&S[1],&S[n+1]);int len=unique(&S[1],&S[n+1])-S-1;
for(int i=1;i<=n;++i)t[i].key=lower_bound(&S[1],&S[len+1],t[i].key)-S;
sort(&t[1],&t[n+1]);
for(int i=1;i<=n;++i)S[i]=t[i].s+S[i-1];
memset(f,63,sizeof(f));
for(int i=1;i<=n+1;++i)
for(int j=0;j<=n;++j)
f[i][i-1][j]=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
f[i][i][j]=t[i].s+(t[i].key!=j)*K;
for(int k=n;k;--k)
for(int l=1;l<=n;++l)
for(int i=1,j=i+l-1;j<=n;++i,++j)
for(int p=i;p<=j;++p)
{
f[i][j][k]=min(f[i][j][k],f[i][p-1][k]+f[p+1][j][k]+S[j]-S[i-1]+K);
if(k<=t[p].key)f[i][j][k]=min(f[i][j][k],f[i][p-1][t[p].key]+f[p+1][j][t[p].key]+S[j]-S[i-1]);
}
printf("%d\n",f[1][n][1]);
return 0;
}


posted @ 2018-05-28 10:59  小蒟蒻yyb  阅读(190)  评论(0编辑  收藏  举报