[概率DP] Topcoder SRM687div2 1000 Queueing

題意:
兩列隊伍,左邊有len1 個人,右邊有len2 個人,問事件左邊沒人但右邊有人的概率。
兩邊收銀員各有一個經驗值參數pF(p,k)=(1/p)(11/p)k1 表示經驗值爲p 的收銀員恰好花費k 秒完成一次收銀的概率。
題解:
首先發現F(p,k) 十分眼熟,滿足幾何分佈,所以每秒成功收銀的概率是1/p ,設左邊成功收銀概率a=1/p1 ,右邊爲b=1/p2
設左邊沒人但右邊有人爲事件A ,則答案是求P(A)
然後就是DP,DP[i][j] 表示左邊有i 人右邊有j 人時達成事件A 的概率。
然後轉移有四個方向:

  1. 左邊成功但右邊失敗,概率是a(1b)
  2. 左邊成功且右邊成功,概率是ab
  3. 左邊失敗但右邊成功,概率是(1a)b
  4. 左邊失敗且右邊失敗,概率是(1a)(1b)

整理出轉移方程。
DP[i][j]=DP[i1][j]a(1b)+DP[i1][j1]ab+DP[i][j1](1a)b+DP[i][j](1a)(1b)

解出DP[i][j]=(DP[i1][j]a(1b)+DP[i1][j1]ab+DP[i][j1](1a)b)/(1(1a)(1b))

初始條件爲DP[0][0]=0DP[0][i]=1(i>=1)

// BEGIN CUT HERE

// END CUT HERE
#line 5 "Queueing.cpp"
#include<vector>
#include<algorithm>
#include<string.h>
using namespace std;
double dp[1005][1005];
class Queueing {
    private:
        void init(){
            memset(dp, 0, sizeof(dp));
        }
    public:
        double probFirst(int len1, int len2, int p1, int p2) {
            init();
            for(int i = 1; i <= len2; ++i) dp[0][i] = 1;
            double a = 1.0/p1, b = 1.0/p2;
            for(int i = 1; i <= len1; ++i){
                for(int j = 1; j <= len2; ++j){
                    dp[i][j] = dp[i-1][j]*a*(1-b)+dp[i][j-1]*(1-a)*b+dp[i-1][j-1]*a*b;
                    dp[i][j] /= (1-(1-a)*(1-b));
                }
            }
            return dp[len1][len2];
        }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章