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

Description


Input


Output
只有一个数字,即你所能得到的整棵树的访问代价与额外修改代价之和的最小值。
Sample Input
4 10
1 2 3 4
1 2 3 4
1 2 3 4
Sample Output
29
HINT

输入的原图是左图,它的访问代价是1×1+2×2+3×3+4×4=30。最佳的修改方案是把输入中的第3个结点的权值改成0,得到右图,访问代价是1×2+2×3+3×1+4×2=19,加上额外修改代价10,一共是29。

 

感觉莫名其妙的A了

我设的状态是f[l,r,k]表示区间[l,r]的元素权值都大于等于k时的最小访问代价之和

然后枚举某个点作为根

1.这个点的权值<k,那么就花费K改成k,f[l,r,k]=min(f[l,r,k],f[l,x-1,k]+f[x+1,r,k]+s[l,r]+K)

2.这个点权值>=k,那么我们可以不花费,也可以花费K改成k,f[l,r,k]=min(f[l,r,k],f[l,x-1,k]+f[x+1,r,k]+s[l,r]+K,f[l,x-1,v[x]]+f[x+1,r,v[x]]+s[l,r])

 1 const
 2     maxn=75;
 3 type
 4     node=record
 5         x,v,c:longint;
 6         flag:boolean;
 7     end;
 8 var
 9     f:array[0..maxn,0..maxn,0..maxn]of longint;
10     a:array[0..maxn]of node;
11     s:array[0..maxn]of longint;
12     n,p,ans:longint;
13  
14 procedure swap(var x,y:node);
15 var
16     t:node;
17 begin
18     t:=x;x:=y;y:=t;
19 end;
20  
21 procedure down(var x:longint;y:longint);
22 begin
23     if x>y then x:=y;
24 end;
25  
26 procedure init;
27 var
28     i,j,cnt,min:longint;
29 begin
30     read(n,p);
31     for i:=1 to n do read(a[i].x);
32     for i:=1 to n do read(a[i].v);
33     for i:=1 to n do read(a[i].c);
34     for i:=n downto 2 do
35         for j:=1 to i-1 do
36             if a[j].x>a[j+1].x then swap(a[j],a[j+1]);
37     for i:=1 to n do s[i]:=s[i-1]+a[i].c;
38     cnt:=0;j:=1;
39     while cnt<n do
40         begin
41             min:=maxlongint;
42             for i:=1 to n do
43                 if a[i].flag=false then down(min,a[i].v);
44             for i:=1 to n do
45                 if (a[i].flag=false) and (a[i].v=min) then
46                 begin
47                     inc(cnt);
48                     a[i].flag:=true;
49                     a[i].v:=j;
50                 end;
51             inc(j);
52         end;
53 end;
54  
55 procedure dp;
56 var
57     i,j,k,l:longint;
58 begin
59     for i:=0 to n-1 do
60         for j:=1 to n-i do
61             for k:=1 to n do
62                 begin
63                     f[j,i+j,k]:=maxlongint;
64                     for l:=j to i+j do
65                         begin
66                             if a[l].v<k then down(f[j,i+j,k],f[j,l-1,k]+f[l+1,i+j,k]+s[i+j]-s[j-1]+p)
67                             else
68                                 begin
69                                     down(f[j,i+j,k],f[j,l-1,k]+f[l+1,i+j,k]+s[i+j]-s[j-1]+p);
70                                     down(f[j,i+j,k],f[j,l-1,a[l].v]+f[l+1,i+j,a[l].v]+s[i+j]-s[j-1]);
71                                 end;
72                         end;
73                 end;
74     ans:=maxlongint;
75     for i:=1 to n do down(ans,f[1,n,i]);
76     writeln(ans);
77 end;
78  
79 begin
80     init;
81     dp;
82 end.
View Code

 

posted @ 2015-07-23 00:25  Randolph87  阅读(155)  评论(0编辑  收藏  举报