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

    题意:

    你试图把一些多米诺骨牌排成直线,然后推倒它们。但是如果你在放骨牌的时候不小心把刚放的骨牌碰倒了,它就会把相临的一串骨牌全都碰倒,

    而你的工作也被部分的破坏了。

    比如你已经把骨牌摆成了DD__DxDDD_D的形状,而想要在x这个位置再放一块骨牌。它可能会把左边的一块骨牌或右边的三块骨牌碰倒,而你将不得不重新摆放这些骨牌。

    这种失误是无法避免的,但是你可以应用一种特殊的放骨牌方法来使骨牌更多的向一个方向倒下。

    给出你要摆放的骨牌数目,以及放骨牌时它向左和向右倒的概率,计算你为完成任务摆放的骨牌数目的平均数。假设你使用了最佳的摆放策略。

    输入将包含至多100个测试点,每个测试点占一行,包含需要摆放的骨牌数目n (1≤n≤1000),以及两个非负实数Pl, Pr,表示骨牌向左和向右倒的概率。保证1<Pl+Pr≤0.5。

    解析:

      假设我们正在放第i个  i的左右两边都已经放好了 那么 有三种情况  左倒   右倒  不倒 

      设放左边的期望次数为El  放右边的期望次数为Er 

      那么E就等于相应 情况乘概率然后相加

      如果不倒 Ei = El + Er + 1;

      如果 左倒 那么我们就要重新放一遍左边 那么次数增加El + 1 次?  仔细想一下 当然不是。。因为如果这次再放的时候又倒了那  所以是Ei - Er

      同理 如果右倒 则是 Ei - El

      所以 Ei = El + Er + 1 + (Ei - Er)* pl + (Ei - El)* pr;

      移项得 

    Ei = min(Ei, (1 - p1) / (1 - p1 - p2) * El + (1 - p2) / (1 - p1 - p2) * Er + 1 / (1 - p1 - p2);
    #include <iostream>
    #include
    <cstdio> #include <sstream> #include <cstring> #include <map> #include <cctype> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <cmath> #include <bitset> #define rap(i, a, n) for(int i=a; i<=n; i++) #define rep(i, a, n) for(int i=a; i<n; i++) #define lap(i, a, n) for(int i=n; i>=a; i--) #define lep(i, a, n) for(int i=n; i>a; i--) #define rd(a) scanf("%d", &a) #define rlld(a) scanf("%lld", &a) #define rc(a) scanf("%c", &a) #define rs(a) scanf("%s", a) #define pd(a) printf("%d ", a); #define plld(a) printf("%lld ", a); #define pc(a) printf("%c ", a); #define ps(a) printf("%s ", a); #define MOD 2018 #define LL long long #define ULL unsigned long long #define Pair pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define _ ios_base::sync_with_stdio(0),cin.tie(0) //freopen("1.txt", "r", stdin); using namespace std; const int maxn = 1700, INF = 0x7fffffff, LL_INF = 0x7fffffffffffffff; int n, m, tot; double dp[maxn]; int main() { int n; double p1, p2; while(cin >> n >> p1 >> p2) { for(int i=1; i<=n; i++) { dp[i] = INF; for(int j=0; j<i; j++) dp[i] = min(dp[i], (1 - p1) / (double) (1 - p1 - p2) * dp[j] + (1 - p2) / (double) (1 - p1 - p2) * dp[i - j - 1]); dp[i] += 1 / (double)(1 - p1 - p2); } printf("%.2f ", dp[n]); } return 0; }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    请教visiouml活动图中动作状态和状态的区别谢谢 软件工程管理 软件规划版
    !!!IT人员迅速提升自我效率的十大方法
    如何在Visio的UML活动图中(判断及控制流)添加文字啊????
    Convert Standard String to System::String
    m_pRecordset遍历记录集之后,m_pRecordsetMoveFirst()为什么会出错
    !!! C++/CLI中使用using namespace System::Windows::Forms;+MessageBox报错最重要的是看MSDN 每个函数的使用例子
    !!!创建 UML 活动图 Visio Office_com
    C#反射之AssemblyCLR/c++可以通过反射调用c#类库
    请允许我进入你的世界
    以赛庆党日
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9733632.html
Copyright © 2011-2022 走看看