HDU5236 Article(期望dp)

来源:互联网 发布:华康字体淘宝可以用吗 编辑:程序博客网 时间:2024/06/05 23:41

Article

传送门1
传送门2
As the term is going to end, DRD begins to write his final article.

DRD uses the famous Macrohard’s software, World, to write his article. Unfortunately this software is rather unstable, and it always crashes. DRD needs to write n characters in his article. He can press a key to input a character at time i+0.1, where i is an integer equal or greater than 0. But at every time i0.1 for integer i strictly greater than 0, World might crash with probability p and DRD loses his work, so he maybe has to restart from his latest saved article. To prevent write it again and again, DRD can press Ctrl-S to save his document at time i. Due to the strange keyboard DRD uses, to press Ctrl-S he needs to press x characters. If DRD has input his total article, he has to press Ctrl-S to save the document.

Since World crashes too often, now he is asking his friend ATM for the optimal strategy to input his article. A strategy is measured by its expectation keys DRD needs to press.

Note that DRD can press a key at fast enough speed.

Input

First line: an positive integer 0T20 indicating the number of cases.
Next T lines: each line has a positive integer n105, a positive real 0.1p0.9, and a positive integer x100.

Output

For each test case: output ”Case #k: ans” (without quotes), where k is the number of the test cases, and ans is the expectation of keys of the optimal strategy.
Your answer is considered correct if and only if the absolute error or the relative error is smaller than 106.

Sample Input

2
1 0.5 2
2 0.4 2

Sample Output

Case #1: 4.000000
Case #2: 6.444444


题意

你现在要打n个字符,但是程序随时可能会崩溃。
你可以在恰当的时机按下 Ctrl−S键,崩溃后,会从最后一次保存的情况继续开始打字。
1. 在每个第i0.1s(i>0)的时候,程序崩溃的概率为p
2. 在每个第is(i0)的时候,你可以一口气按下x个键来存盘
3. 在每个第i+0.1s(i0)的时候,你可以按下一个键来打字
求采取最优策略下,打完这n个字符,并且最后存盘,总按键次数的期望。

分析

定义dp[i]表示敲出i个字符时按键期望。
因为敲第i个字符首先得敲出i1个字符,然后敲下一个字符时, 有两种可能, p概率会丢失,(1p)概率不会丢失, 对于丢失的情况就还得重新敲dp[i]次, 不丢失的情况就只有一次就成功, 所以是(1p)1。于是得到

dp[i]=dp[i1]+p(1+dp[i])+(1p),

然后进行类似解方程的操作得到
dp[i]=(dp[i1]+1)1p.

另外,我们可以发现dp数组是指数增长的,而且11p>1,所以随着i的增大, dp[i]增大的越快。我们可以枚举保存的次数k, 保存k次就相当于把n个字符分成k部分来完成, 由上面结论可知, 这k部分尽量均匀。

CODE

#include<cstdio>#define N 100005typedef double db;int n,x;db p,dp[N];inline void Min(db &x,db y) {if(x>y)x=y;}int main() {    int t;    scanf("%d",&t);    for(int cas=1; cas<=t; cas++) {        scanf("%d%lf%d",&n,&p,&x);        for(int i=1; i<=n; i++)dp[i]=(dp[i-1]+1)/(1-p);        db ans=dp[n]+x;        for(int i=2; i<=n; i++)Min(ans,dp[n/i+1]*(n%i)+dp[n/i]*(i-n%i)+i*x);        printf("Case #%d: %.6f\n",cas,ans);    }    return 0;}
原创粉丝点击