bzoj 1564 [NOI2009]二叉查找树(树形DP)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1564 [NOI2009]二叉查找树(树形DP)相关的知识,希望对你有一定的参考价值。

 

【题目链接】

 

    http://www.lydsy.com/JudgeOnline/problem.php?id=1564

 

【题意】

 

    给定一个Treap,总代价为深度*距离之和。可以每次以K的代价修改权值,问最小代价。

 

【思路】

 

    数据值是不变的,因此Treap的中序遍历是唯一的。先将数据按照数据值排序,得到其中序遍历。

  然后将权值离散化到[1,n]区间内。

    设f[l][r][w]为区间[l,r]内的权值都比w大时的最小代价,则有转移式:

        f[l][r][w]=min { f[l][k-1][w]+f[k+1][r][w]+K+c(l,r) },a[k].w>=w

       f[l][r][w]=min { f[l][k-1][a[k].w]+f[k+1][r][a[k].w]+c(l,r) }

    记忆化搜索比较好写lalala

 

【代码】

 

 1 #include<set>
 2 #include<cmath>
 3 #include<queue>
 4 #include<vector>
 5 #include<cstdio>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
11 using namespace std;
12 
13 typedef long long ll;
14 const int N = 105;
15 const int inf = 1e9;
16 
17 struct Node 
18 {
19     int dat,w,c;
20     bool operator < (const Node& rhs) const 
21     {
22         return dat<rhs.dat;
23     }
24 } a[N];
25 
26 int n,K,sumc[N],f[N][N][N];
27 pair<int,int> b[N];
28 
29 int dp(int l,int r,int w)
30 {
31     int& ans=f[l][r][w];
32     if(l>r) return ans=0;
33     if(ans!=-1) return ans;
34     ans=inf;
35     FOR(k,l,r) {
36         if(a[k].w>=w)
37             ans=min(ans,dp(l,k-1,a[k].w)+dp(k+1,r,a[k].w)+sumc[r]-sumc[l-1]);
38         ans=min(ans,dp(l,k-1,w)+dp(k+1,r,w)+sumc[r]-sumc[l-1]+K);
39     }
40     return ans;
41 }
42 
43 int main()
44 {
45 //    freopen("in.in","r",stdin);
46 //    freopen("out.out","w",stdout);
47     memset(f,-1,sizeof(f));
48     scanf("%d%d",&n,&K);
49     FOR(i,1,n) scanf("%d",&a[i].dat);
50     FOR(i,1,n) scanf("%d",&a[i].w);
51     FOR(i,1,n) scanf("%d",&a[i].c);
52     sort(a+1,a+n+1);
53     FOR(i,1,n)
54         b[i]=make_pair(a[i].w,i);
55     sort(b+1,b+n+1);
56     FOR(i,1,n)
57         a[b[i].second].w=i,
58         sumc[i]=sumc[i-1]+a[i].c;
59     
60     int ans=inf;
61     FOR(i,1,n)
62         ans=min(ans,dp(1,n,i));
63     printf("%d",ans);
64     return 0;
65 }

 

以上是关于bzoj 1564 [NOI2009]二叉查找树(树形DP)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1564: [NOI2009]二叉查找树( dp )

bzoj1564 二叉查找树

NOI2009 二叉查找树 区间dp

[NOI2009]二叉查找树

bzoj4198: [Noi2015]荷马史诗

省选/NOI刷题Day1