相当于在不同模块之间来回移动
#include<cstdio> #include<iostream> #include<cstring> using namespace std; //最大可能的模块数 const int maxn = 1 << 15 + 10; //轮数 int M; //赌赢概率 double P; //本钱 int X; //dp[i][j] 表示第i轮每个模块赢到100W的概率 //这里采用滚动数组节约内存 double dp[2][maxn]; //新技能get, 滚动数组 double *prv = dp[0], *nxt = dp[1]; int main () { memset(dp, 0, sizeof(dp)); cin >> M >> P >> X; int n = 1 << M; prv[n] = 1.0; for(int i= 0; i< M; i++){ for(int j= 0; j<= n; j++){ int ub = j > n-j ? n-j : j; double temp = 0.0; //枚举可能跨越的模块的数 for(int k= 0; k<= ub; k++) if(temp < P*prv[j+k] + (1-P)*prv[j-k]) //这把赌赢的概率*赌赢后赢到100W的概率 //这把赌输的概率*赌输后赢到100W的概率 temp = P*prv[j+k] + (1-P)*prv[j-k]; nxt[j] = temp; } //新技能get, 滚动数组 swap(prv, nxt); } //判断 X 在哪个模块中 int pos = (double) X / 1000000 * n; printf("%f\n", prv[pos]); return 0; }