AOJ 2301: Sleeping Time

Sleeping Time
コード

難易度Blue 350 (非公式難易度表)

「k回の睡眠でR=r, L=lとした時のPP」を返す関数retを考えて、深さ優先探索を行う発想は自然。
だが、これだけでは2^30で計算が間に合わない。

なので、l, rとP, Eの関係に枝刈り条件を加える。
ret内のl-rを呼び出し回数に関して指数関数的に収束させていくので、この条件はかなり強い枝刈りが可能である。

#include <iostream>
#include <cstdio>
using namespace std;
#define abs(a) ((a) > 0 ? (a) : -(a))
 
double P, E, T;
double ret(double k, double r, double l)
{
    double h = (r + l) / 2;
    if (k == 0) 
        return (abs(h-T) < E ? 1.0 : 0.0);
    if (l < T - E)
        return 0.0;
    if (r > T + E) 
        return 0.0;
    if (T - E < r && l < T + E) 
        return 1.0;
    if ((r+l)/2 >= T) 
        return P * ret(k-1, r, h) + (1.0 - P) * ret(k-1, h, l);
    else
        return P * ret(k-1, h, l) + (1.0 - P) * ret(k-1, r, h);
}
 
int main(void)
{
    double K, R, L;
    cin >> K >> R >> L >> P >> E >> T;
    P = 1 - P;
 
    printf("%.6f", ret(K, R, L));
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>