【NOI2008】 奥运物流

题目描述
奥运物流
【问题描述】
2008 北京奥运会即将开幕,
举国上下都在为这一盛事做好准备。
为了高效率、
成功地举办奥运会,对物流系统进行规划是必不可少的。
物流系统由若干物流基站组成,以 1...N 进行编号。每个物流基站 i 都有且
仅有一个后继基站 Si,而可以有多个前驱基站。基站 i 中需要继续运输的物资都
将被运往后继基站 Si,显然一个物流基站的后继基站不能是其本身。编号为 1 的
从任何物流基站都可将物资运往控制基站。
注意控制基
物流基站称为控制基站,
站也有后继基站,以便在需要时进行物资的流通。在物流系统中,高可靠性与低
成本是主要设计目。对于基站 i,我们定义其“可靠性” R (i ) 如下:
设物流基站 i 有 w 个前驱基站 P1, P2 ,Pw ,即这些基站以 i 为后继基站,则基站 i 的可靠性 R(i)满足下式:
                     w
R(i ) = Ci + k ∑ R( Pj )
                    j =1
其中 Ci 和 k 都是常实数且恒为正,且有 k 小于 1。
整个系统的可靠性与控制基站的可靠性正相关,
我们的目标是通过修改物流系统,即更改某些基站的后继基站,使得控制基站的可靠性 R(1)尽量大。但由于经费限制,最多只能修改 m 个基站的后继基站,并且,控制基站的后继基站不可被修改。因而我们所面临的问题就是,如何修改不超过 m 个基站的后继,使
得控制基站的可靠性 R(1)最大化。
【输入格式】
输入文件 trans.in 第一行包含两个整数与一个实数,N, m, k。其中 N 表示基
站数目,m 表示最多可修改的后继基站数目,k 分别为可靠性定义中的常数。
第二行包含 N 个整数,分别是 S1, S2...SN,即每一个基站的后继基站编号。
第三行包含 N 个正实数,分别是 C1, C2...CN,为可靠性定义中的常数。
【输出格式】
输出文件 trans.out 仅包含一个实数,为可得到的最大 R(1)。精确到小数点两
位。
【输入样例】
4 1 0.5
2313
10.0 10.0 10.0 10.0
【输出样例】
30.00
【样例说明】
原有物流系统如左图所示,4 个物流基站的可靠性依次为 22.8571,21.4286,
25.7143,10。
最优方案为将 2 号基站的后继基站改为 1 号,如右图所示。 此时 4 个基站
的可靠性依次为 30,25,15,10。
【数据规模和约定】
本题的数据,具有如下分布:
测试数据编号            N                              M
166
21212
360                           0
460                           1
560                          N-2
6~106060
对于所有的数据,满足 m ≤ N ≤ 60,Ci ≤ 106,0.3 ≤ k < 1,请使用双精度实
数,无需考虑由此带来的误差。

 

题解

 

解法1:贪心
  1 (*
  2     *Problem:    NOI2008 奥运物流
  3     *Author :    Chen Yang
  4     *Time   :    2012.5.20
  5     *State  :    70分
  6     *Memo    :    贪心
  7 *)
  8 program trans;
  9 type
 10   ty1=^ty2;
 11   ty2=record
 12      x:longint;
 13      next:ty1;
 14   end;
 15 var
 16   n,m,i:longint;
 17   k,ans:extended;
 18   father:array[0..100] of longint;
 19   c,r:array[0..100] of extended;
 20   get:array[0..100] of boolean;
 21   first:array[0..100] of ty1;
 22 //=====================
 23 procedure insert(x,y:longint);
 24 var
 25   p:ty1;
 26 begin
 27   new(p);
 28   p^.x:=y;
 29   p^.next:=first[x];
 30   first[x]:=p;
 31 end;
 32 //=====================
 33 procedure find(i:longint; kx:extended);
 34 var
 35   p:ty1;
 36   x:extended;
 37   son:longint;
 38 begin
 39   p:=first[i]; x:=0; son:=0;
 40   while p<>nil do
 41   begin
 42     if not get[p^.x] then
 43     begin
 44       find(p^.x,kx);
 45       x:=x+r[p^.x];
 46     end else son:=p^.x;
 47     p:=p^.next;
 48   end;
 49   if not get[i] then r[i]:=x*k+c[i] else ans:=ans+c[i]*kx+x*kx*k;
 50   if son>0 then find(son,kx*k);
 51 end;
 52 //=====================
 53 procedure work;
 54 var
 55   i,t:longint;
 56   kx:extended;
 57 begin
 58   fillchar(first,sizeof(first),0);
 59   fillchar(get,sizeof(get),false);
 60   for i:=2 to n do insert(father[i],i);
 61   ans:=0; t:=0;
 62   i:=1;
 63   while father[i]<>1 do
 64   begin
 65     inc(t);
 66     get[i]:=true;
 67     i:=father[i];
 68   end;
 69   get[i]:=true; inc(t);
 70   find(1,1);
 71   kx:=1;
 72   for i:=1 to t do kx:=kx*k;
 73   ans:=ans/(1-kx);
 74 end;
 75 //=====================
 76 procedure main;
 77 var
 78   i,t,k,j:longint;
 79 begin
 80   work; r[1]:=ans;
 81   if m=0 then writeln(ans:0:2) else
 82   if m=n-2 then
 83   begin
 84     for i:=2 to n do father[i]:=1;
 85     work;
 86     writeln(ans:0:2);
 87   end else
 88   begin
 89     for j:=1 to m do
 90     begin
 91       k:=0;
 92       for i:=2 to n do
 93       if father[i]<>1 then
 94       begin
 95         t:=father[i]; father[i]:=1;
 96         work;
 97         if r[1]<ans then begin r[1]:=ans; k:=i; end;
 98         father[i]:=t;
 99       end;
100       father[k]:=1;
101     end;
102     writeln(r[1]:0:2);
103   end;
104 end;
105 //=====================
106 begin
107   assign(input,'trans.in'); reset(input);
108   assign(output,'trans.out'); rewrite(output);
109   read(n,m,k);
110   for i:=1 to n do read(father[i]);
111   for i:=1 to n do read(c[i]);
112   main;
113   close(input); close(output);
114 end.

 

解法2:树形DP
 1 (*
 2     *Problem:    NOI2008 奥运物流
 3     *Author :    Chen Yang
 4     *Time   :    2012.5.20
 5     *State  :    AC
 6     *Memo    :    树形DP,多重背包
 7 *)
 8 program trans;
 9 uses math;
10 const maxn=65;
11 var
12   n,m,i,len:longint;
13   k,ans:extended;
14   fa:array[0..maxn] of longint;
15   c,kk,ff:array[0..maxn] of extended;
16   f,g:array[0..maxn,0..maxn,0..maxn] of extended;
17 //==================
18 procedure find(x,d:longint);
19 var
20   i,j,k,l:longint;
21 begin
22   for i:=2 to n do if fa[i]=x then find(i,d+1);
23   for k:=min(2,d) to d do
24   begin
25     for i:=0 to m do ff[i]:=0;
26     for i:=2 to n do if fa[i]=x then
27     for j:=m downto 0 do
28     for l:=j downto 0 do
29     if ff[j]<ff[l]+g[i,j-l,k] then ff[j]:=ff[l]+g[i,j-l,k];
30     for i:=0 to m do f[x,i,k]:=ff[i]+kk[k]*c[x];
31   end;
32   if d<>1 then
33   begin
34     for i:=0 to m do ff[i]:=0;
35     for i:=2 to n do if fa[i]=x then
36     for j:=m downto 0 do
37     for l:=j downto 0 do
38     if ff[j]<ff[l]+g[i,j-l,1] then ff[j]:=ff[l]+g[i,j-l,1];
39     for i:=1 to m do f[x,i,1]:=ff[i-1]+kk[1]*c[x];
40   end;
41   for j:=0 to m do
42   for k:=0 to d-1 do
43   if f[x,j,k+1]>f[x,j,1] then g[x,j,k]:=f[x,j,k+1] else g[x,j,k]:=f[x,j,1];
44 end;
45 //==================
46 procedure work(father:longint);
47 var
48   i,j,k:longint;
49   t:extended;
50 begin
51   fillchar(f,sizeof(f),0);
52   fillchar(g,sizeof(g),0);
53   for i:=2 to n do if fa[i]=1 then find(i,1);
54   for i:=0 to m do ff[i]:=0;
55   for i:=2 to n do if fa[i]=1 then
56   for j:=m downto 0 do
57   for k:=j downto 0 do
58   if ff[j]<ff[k]+f[i,j-k,1] then
59   ff[j]:=ff[k]+f[i,j-k,1];
60   t:=0;
61   for i:=0 to m-1 do
62   if t<ff[i] then t:=ff[i];
63   if (father=1)and(ff[m]>t) then t:=ff[m];
64   t:=(t+c[1])/(1-kk[len]);
65   if ans<t then ans:=t;
66 end;
67 //==================
68 procedure main;
69 var
70   i,t:longint;
71 begin
72   kk[0]:=1; for i:=1 to n do kk[i]:=kk[i-1]*k;
73   i:=fa[1]; len:=1;
74   while i<>1 do
75   begin
76     inc(len); t:=fa[i]; fa[i]:=1;
77     work(t);
78     fa[i]:=t; i:=t;
79   end;
80   writeln(ans:0:2);
81 end;
82 //==================
83 begin
84   assign(input,'trans.in'); reset(input);
85   assign(output,'trans.out'); rewrite(output);
86   read(n,m,k);
87   for i:=1 to n do read(fa[i]);
88   for i:=1 to n do read(c[i]);
89   main;
90   close(input); close(output);
91 end.

转载于:https://www.cnblogs.com/datam-cy/archive/2012/05/22/2513782.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值