zoukankan      html  css  js  c++  java
  • UVA10529 Dumb Bones

    传送门

    翻译有些不清楚,意思就是骨牌不一定要按从左到右的顺序放,可以左边放一个,右边放一个,再中间放一个

    然后每个骨牌都可能往左或往右倒,一旦倒了,倒的一边的所有骨牌都要重新放

    然后问你,最小期望放置次数是多少

    考虑每个骨牌的影响,设$f [ i ]$ 表示放$ i $个骨牌的的最小期望放置次数

    那么显然 $f [ 1 ] = 1/(1-pl-pr)$

    枚举此次放置的位置$ j $,设左边有$ L $个骨牌,右边有 $R$ 个骨牌

    那么期望花费就是左边的期望花费$f[L]$加右边的期望花费$f[R]$

    加上放最后一块的期望$frac{(1+P_lcdot f[L]+P_rcdot f[R])}{(1-P_l-P_r)}$

    $P_lcdot f[L]$ 是骨牌往左倒的期望花费,$P_rcdot f[R]$同理,注意还要保证最后放置时不倒,所以期望要再除一个成功概率

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    inline ll read()
    {
        ll x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1e3+7;
    const double INF=1e9+7;
    int n;
    double f[N],pl,pr,t;//t是放置一个骨牌的成功概率
    inline double slove(int l,int r)
    {
        return f[l]+f[r]+(1+pl*f[l]+pr*f[r])/t;
    }
    int main()
    {
        n=read();
        while(n)
        {
            scanf("%lf%lf",&pl,&pr);
            t=1.0-pl-pr;
            f[0]=0; f[1]=1/t;
            for(int i=2;i<=n;i++)
            {
                f[i]=slove(0,i-1);
                for(int j=1;j<i;j++)
                    f[i]=min(f[i],slove(j,i-j-1));
            }
            printf("%.2lf
    ",f[n]);
            n=read();
        }
        return 0;
    }

    可以发现随着 j 的变化,期望是一个下凹函数

    随着 i 的增长,下凹的位置是保持不降的,所以我们可以得出一个均摊O(n)的算法

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    inline ll read()
    {
        ll x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1e3+7;
    const double INF=1e9+7;
    int n;
    double f[N],pl,pr,t;
    inline double slove(int l,int r)
    {
        return f[l]+f[r]+(1+pl*f[l]+pr*f[r])/t;
    }
    int main()
    {
        n=read();
        while(n)
        {
            scanf("%lf%lf",&pl,&pr);
            t=1.0-pl-pr;
            f[0]=0; f[1]=1/t;
            int pos=0;//pos记录上一次下凹的位置
            for(int i=2;i<=n;i++)
            {
                f[i]=slove(pos,i-pos-1);
                for(int j=pos+1;j<i;j++)//下凹位置保持不降
                {
                    double s=slove(j,i-j-1);
                    if(s<=f[i]) { f[i]=s; pos=j; }
                    else break;
                }
            }
            printf("%.2lf
    ",f[n]);
            n=read();
        }
        return 0;
    }
  • 相关阅读:
    (4.7)怎么捕获和记录SQL Server中发生的死锁?
    SQLSERVER排查CPU占用高的情况
    (4.6)sql server索引缺失提示
    (4.14)向上取整、向下取整、四舍五入取整的实例
    mysql大致学习路径
    (2)linux未使用eth0,未使用IPV4导致无法连接
    (4.13)sql server参数嗅探(parameter sniffing)
    完美女人
    关于box-sizing
    什么是担当
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9804639.html
Copyright © 2011-2022 走看看