题意:n条通道和m百万元,每一条通道有三种情况,一是直接出去,概率是p,二是碰上士兵,给1百万块再回去,概率是q,或者是死路,概率是1-p-q。问最终出去时最优可能性。
思路:概率dp,既然问最优可能性,肯定是最有可能跑出去的情况最好了,就算跑不出去也要少碰士兵,所以先按p/q从大到小排序,然后dp[i][j]代表在第i个通道,还有j万元的时候能出去的概率。
能直接出去的话,最终结果加上dp[i][j]*p;如果碰上士兵就dp[i+1][j-1]+=dp[i][j]*q;如果是死路,就dp[i+1][j]+=dp[i][j]*(1-p-q);
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<ctype.h>
#include<algorithm>
#include<deque>
#include<functional>
#include<iterator>
#include<vector>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<sstream>
#define CPY(A, B) memcpy(A, B, sizeof(A))
typedef long long LL;
typedef unsigned long long uLL;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-9;
const double OO = 1e20;
const double PI = acos (-1.0);
int dx[]= {0,1,1,1,0,-1,-1,-1};
int dy[]= {1,1,0,-1,-1,-1,0,1};
int gcd (const LL &a, const LL &b) {return b==0?a:gcd (b,a%b);}
using namespace std;
double dp[1010][11];//小心double
struct node {
double p,q;
bool operator < (const node &a) const {
return p/q>a.p/a.q;
}
} num[1010];
int main() {
int T,cas=1; scanf ("%d",&T);
while (T--) {
int n,m; scanf ("%d%d",&n,&m);
for (int i = 0; i < n; i++) {
scanf ("%lf%lf",&num[i].p,&num[i].q);
}
sort (num,num+n);
double ans=0.0;
memset (dp,0,sizeof (dp) );
dp[0][m]=1.0;
for (int i=0; i<n; i++) {
for (int j=m; j>=0; j--) {
ans+=num[i].p*dp[i][j];
if (j>=1) {dp[i+1][j-1]+=dp[i][j]*num[i].q;}
dp[i+1][j]+=dp[i][j]* (1-num[i].q-num[i].p);
}
}
printf ("Case %d: %.5f\n",cas++,ans);
}
return 0;
}