GDKOI2016Day1第二题 不稳定的传送门 解题报告
2016-02-26 19:27
411 查看
GDKOI2016Day1第二题T2题解
题目描述略
样例解释:
首先,数组Fi表示由i至n的最优期望方案的值。先将i连向i+1的那条边看成一条费用为W,成功传送的概率为P,P=1(100%),门的终点为U,U=i+1
当我们做到第i个点时,我们可以通过已做完的点j的Fj的值转移过来。
假设做到了第i个点,考虑门的使用顺序,对门的顺序进行一次全排列,选最优方案,便是Fi的值。
用样例来举例子。
i=4时,Fi=0
i=3时,只能选择一扇门,故Fi=W1+P1*FU1=30
(U1=4,P1=1,W1=30)
i=2时,可以选择两扇门,第一扇是(U1=3,P1=1,W1=30)、
第二扇是(U2=3,P2=0.9,W2=10)
对这两扇门的顺序进行全排列,发现先放第二扇门更优。
具体如下:
对应内容 | 第二扇门 | 第一扇门 |
---|---|---|
使用此门传送的概率 | 1 | 1-P2=0.1 |
门费用 | W2=10 | W1=30 |
传送的终点 | U2=3 | U1=3 |
总期待费用V | V2=W2+P2*FU2=37 | V1=(1-P2)(W1+P1*FU1)=6 |
i=1时,一样有两扇门可以选,第一扇是(U1=4,P1=0.5,W1=30)、
第二扇是(U2=2,P2=1,W2=30)
对这两扇门的顺序进行全排列,发现先放第一扇门更优。
具体如下:
对应内容 | 第一扇门 | 第二扇门 |
---|---|---|
使用此门传送的概率 | 1 | 1-P1=0.5 |
门费用 | W1=30 | W2=30 |
传送的终点 | U1=4 | U2=2 |
总期待费用V | V1=W1+P1*FU1=30 | V2=(1-P1)(W2+P2*FU2)=36.5 |
所以,答案就是66.5
30分算法
每个点有最多不超过5扇门,枚举门的使用顺序,选最优答案即可。100分算法
可以枚举门的使用顺序,那么能不能通过某种方式求出最优的使用顺序呢?不妨先将一种门(共k扇门)的使用顺序的期望值列出来。
Fi=W1+P1FU1+(1-P1)(W2+P2FU2+(1-P2)(W3+P3FU3+(1-P3)(……)))
设 1-Pi=Vi,Wi+PiFUi=Ki
则Fi=W1+V1(W2+V2(W3+V3(…)))
将这个式子拆括号
则Fi=W1+V1W2+V1V2W3+V1V2V3W4…+V1V2~Vk−2Vk−1Wk
假设已经放了前q扇门,且为最优解,接下来考虑该放哪扇门才是最优的。假设现在有两扇门i,j可选择,如果先放第i扇门更优则一定满足
W1+V1W2+V1V2W3+V1V2V3W4…+V1V2~VqWi+V1V2~VqViWj
<W1+V1W2+V1V2W3+V1V2V3W4…+V1V2~VqWj+V1V2~VqVjWi
化简得
Wi+ViWj<Wj+VjWi
Wi-VjWi<Wj-ViWj
(1-Vj)Wi<(1-Vi)Wj
(1−Vj)Wj<(1−Vj)Wj
即PjWj+VjWj<PiWi+ViWi
PiWi+ViWi>PjWj+VjWj
此时,含i和j的项全部移到了一边,也就是说上述不等式成立时,先放i比先放j更优,且如果i比j优,j比l优,则i比l优,具有了传递性。
现在只需按照 PiWi+ViWi从大到小排序,便可以得到最优的门的使用顺序了.
Code(Pascal)
var f,bl,px:array[0..1000000] of extended; door:array[0..1000000,1..3] of longint; en:array[0..1000000] of longint; n,m,j,k,l,i,o,p:longint; dqbl:extended; procedure qsort(l,r:longint); var i,j,m:longint; begin i:=l; j:=r; m:=door[(l+r) div 2,1]; repeat while door[i,1]<m do inc(i); while door[j,1]>m do dec(J); IF i<=j then begin door[0]:=door[i]; door[i]:=door[j]; door[j]:=door[0]; bl[0]:=bl[i]; bl[i]:=bl[j]; bl[j]:=bl[0]; inc(i); dec(j); end; until i>j; if l<j then qsort(l,j); if i<r then qsort(i,r); end; procedure kp(l,r:longint); var i,j:longint; m:extended; begin i:=l; j:=r; m:=px[(l+r) div 2]/bl[(l+r) div 2]; repeat while px[i]/bl[i]<m do inc(i); while px[j]/bl[j]>m do dec(j); if i<=j then begin px[0]:=px[i]; px[i]:=px[j]; px[j]:=px[0]; bl[0]:=bl[i]; bl[i]:=bl[j]; bl[j]:=bl[0]; door[0]:=door[i]; door[i]:=door[j]; door[j]:=door[0]; inc(i); dec(j); end; until i>j; if l<j then kp(l,j); if i<r then kp(i,r); end; begin assign(input,'portal.in'); reset(input); assign(output,'portal.out'); rewrite(output); readln(n,m); for i:=1 to n-1 do begin read(p); door[i,1]:=i; door[i,2]:=i+1; door[i,3]:=p; bl[i]:=1; inc(en[i]); end; for i:=1 to m do begin readln(door[i+n-1,1],door[i+n-1,2],bl[i+n-1],door[i+n-1,3]); inc(en[door[i+n-1,1]]); end; qsort(1,n+m-1); for i:=2 to n do en[i]:=EN[I-1]+EN[I]; en[0]:=0; f :=0; for i:=n-1 downto 1 do begin for l:=en[i-1]+1 to en[i] do px[l]:=(door[l,3]+bl[l]*f[door[l,2]]); kp(en[i-1]+1,en[i]); f[i]:=0; for l:=en[i] downto en[i-1]+1 do f[i]:=f[i]*(1-bl[l])+px[l]; end; writeln(f[1]:0:2); close(input); close(output); end.
相关文章推荐
- c# 抗变 协变
- PHP 表单验证
- VS 2013搭建PCL,不需要Cmake
- 单链表的建立与打印
- redis 集合命令
- codeforces 629C Famil Door and Brackets(dp)
- 学而不思则罔
- iOS内存分配
- 求树的叶子结点的个数
- Android:ScrollView和SwipeRefreshLayout高度测量
- 创建安卓应用的 30 个经验教训
- iOS上传照片旋转90度解决方法
- 部署搭建 puppet
- Codeforces 625D Finals in arithmetic(Codeforces Round #342 (Div. 2) D) 题解
- 多态之虚函数
- 创建安卓应用的 30 个经验教训
- [Leetcode]@python 100. Same Tree
- linux下socket编程-UDP
- 利用Gson实现简单的json字符串解析
- 5-3 hadoop集群搭建