1. 题目描述
长度为n的等待队列,tomato处于第m个,有如下四种可能:
(1)激活失败,概率为$p_1$,队列中的顺序不变;
(2)连接失败,概率为$p_2$,队头玩家重新排在队尾;
(3)激活成功,概率为$p_3$,队头出队;
(4)服务器down机,概率为$p_4$,队伍停止。
问当服务器当机时,tomato处在队列前k个人的概率是多少?
2. 基本思路
这显然是个概率DP。dp[i][j]表示队伍中有i个人,tomato处在第j个满足所求的概率。
egin{align}
j=1, (1-p_1) imes dp[i][j] &= p_2 imes dp[i][i] + p_4 \
jin [2,k], (1-p_1) imes dp[i][j] &= p_2 imes dp[i][j-1] + p_3 imes dp[i-1][j-1] + p_4 \
j>k, (1-p_1) imes dp[i][j] &= p_2 imes dp[i][j-1] + p_3 imes dp[i-1][j-1]
end{align}
显然,对于$forall i$均存在i个等式,组成方程组。可以通过(1)式代入,解出dp[i][i]。
注意$p_4
ightarrow 0$时,即不会发生down机的情况。概率为0。
3. 代码
1 /* 4089 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <bitset> 12 #include <algorithm> 13 #include <cstdio> 14 #include <cmath> 15 #include <ctime> 16 #include <cstring> 17 #include <climits> 18 #include <cctype> 19 #include <cassert> 20 #include <functional> 21 #include <iterator> 22 #include <iomanip> 23 using namespace std; 24 //#pragma comment(linker,"/STACK:102400000,1024000") 25 26 #define sti set<int> 27 #define stpii set<pair<int, int> > 28 #define mpii map<int,int> 29 #define vi vector<int> 30 #define pii pair<int,int> 31 #define vpii vector<pair<int,int> > 32 #define rep(i, a, n) for (int i=a;i<n;++i) 33 #define per(i, a, n) for (int i=n-1;i>=a;--i) 34 #define clr clear 35 #define pb push_back 36 #define mp make_pair 37 #define fir first 38 #define sec second 39 #define all(x) (x).begin(),(x).end() 40 #define SZ(x) ((int)(x).size()) 41 #define lson l, mid, rt<<1 42 #define rson mid+1, r, rt<<1|1 43 44 const double eps = 1e-8; 45 const int maxn = 2005; 46 double dp[maxn][maxn]; 47 double P[maxn]; 48 int n, kth, k; 49 double p1, p2, p3, p4; 50 51 void solve() { 52 if (p4 < eps) { 53 puts("0.00000"); 54 return ; 55 } 56 57 dp[1][1] = p4 / (1-p1-p2); 58 double p21 = p2 / (1-p1); 59 double p31 = p3 / (1-p1); 60 double p41 = p4 / (1-p1); 61 rep(i, 2, n+1) { 62 double coef = 0.0, cons = 0.0; 63 64 rep(j, 1, i+1) { 65 if (j == 1) { 66 coef = p21; 67 cons = p41; 68 } else if (j <= k) { 69 cons = p41 + p31 * dp[i-1][j-1] + p21 * cons; 70 coef = p21 * coef; 71 } else { 72 cons = p31 * dp[i-1][j-1] + p21 * cons; 73 coef = p21 * coef; 74 } 75 } 76 77 dp[i][i] = cons / (1.0 - coef); 78 rep(j, 1, i) { 79 if (j == 1) { 80 dp[i][j] = p21 * dp[i][i] + p41; 81 } else if (j <= k) { 82 dp[i][j] = p21 * dp[i][j-1] + p31 * dp[i-1][j-1] + p41; 83 } else { 84 dp[i][j] = p21 * dp[i][j-1] + p31 * dp[i-1][j-1]; 85 } 86 } 87 } 88 89 double ans = dp[n][kth]; 90 printf("%.05lf ", ans); 91 } 92 93 int main() { 94 ios::sync_with_stdio(false); 95 #ifndef ONLINE_JUDGE 96 freopen("data.in", "r", stdin); 97 freopen("data.out", "w", stdout); 98 #endif 99 100 while (cin >> n >> kth >> k >> p1 >> p2 >> p3 >> p4) { 101 solve(); 102 } 103 104 #ifndef ONLINE_JUDGE 105 printf("time = %d. ", (int)clock()); 106 #endif 107 108 return 0; 109 }