输入包括一个整数n(0 ≤ n ≤ 500),即机器人行走的步数。
输出一个实数,表示红色格子的期望个数,保留一位小数。
4
3.4
f[1]=2; f[2]=2.5; for(int i=3;i<=n;i++) f[i]=(i-1)*f[i-2]/i+2*f[i-1]/i; printf("%.1lf\n",f[n]);
参考自:https://blog.csdn.net/xiaxzhou/article/details/73382283
dp[i][j][k]dp[i][j][k]表示走了ii步后,纸带上有jj个红色格子时,机器人位于第kk个红色格子上的概率
dp[0][1][1]=1
dp[0][1][1]=1
则dp[i][j][k]的概率会转移到dp[i+1][][]的两个位置上:
机器人位于最左边红格子:
dp[i][j][1]/2dp[i][j][1]/2 的概率会转移到dp[i+1][j+1][1]dp[i+1][j+1][1]
dp[i][j][1]/2dp[i][j][1]/2 的概率会转移到dp[i+1][j][2]dp[i+1][j][2]
机器人位于最右边红格子:
dp[i][j][j]/2dp[i][j][j]/2 的概率会转移到dp[i+1][j+1][j+1]dp[i+1][j+1][j+1]
dp[i][j][j]/2dp[i][j][j]/2 的概率会转移到dp[i+1][j][j−1]dp[i+1][j][j−1]
其余情况:
dp[i][j][k]/2dp[i][j][k]/2的概率会转移到dp[i+1][j][k+1]dp[i+1][j][k+1]
dp[i][j][k]/2dp[i][j][k]/2的概率会转移到dp[i+1][j][k−1]dp[i+1][j][k−1]
最终走完n步后,加权求和即为期望
#include <vector> #include <iostream> #include <numeric> #include <iomanip> using namespace std; vector>> dp; vector vec; vector> vec_2; double func(int n) { vec.resize(503); vec_2.resize(503, vec); dp.resize(2, vec_2); dp[0][1][1] = 1;//一步不走 int prestep, curstep; for (auto i = 1; i <= n; ++i) { prestep = (i - 1) % 2; curstep = i % 2; for (auto j = 0; j <= n + 1; ++j) for (auto k = 0; k <= n + 1; ++k) dp[curstep][j][k] = 0;//初始化数组 for (auto j = 0; j <= n + 1; ++j) for (auto k = 1; k <= n + 1; ++k) { if (k == 1)//向左 dp[curstep][j + 1][k] += dp[prestep][j][k] / 2.; else dp[curstep][j][k - 1] += dp[prestep][j][k] / 2.; if (k == j)//向右 dp[curstep][j + 1][k + 1] += dp[prestep][j][k] / 2.; else dp[curstep][j][k + 1] += dp[prestep][j][k] / 2.; } } curstep = n % 2; double result(0); for (auto j = 0; j <= n + 1; ++j) { double a(0); for (auto i = 0; i < 501; ++i) a += dp[curstep][j][i]; result += (double)j*accumulate(dp[curstep][j].begin(), dp[curstep][j].end(), 0.);//累加函数 } return result; } int main() { int n; n = 500; cin >> n; cout << fixed << setprecision(1) << func(n); return 0; }
#include <iostream>
//思路:利用三维数组 // dp[i%2][j][k]表示走了i步之后恰好有j个红色格子,并且此时机器人正好在第k个红色格子上的概率。时间复杂度O(n^3) // 只使用i%2的原因是,现在只和前一个情况有关 import java.text.DecimalFormat; import java.util.Scanner; public class Main { public static void main(String[] args){ int maxn = 500+5; double[][][] dp = new double[2][maxn][maxn]; Scanner in = new Scanner(System.in); int n = in.nextInt(); // 走的步数 double ans = 0; dp[0][1][0] = 1.0; // 第0步,有一个红格子,在第0个红格子上,的概率为1 for(int i=1;i<=n;i++){ int cur = i%2; // 0,1,0,1... int old = 1-(i%2); for(int j=1;j<=i;j++) // 现在是第n次,则第n-1次最多是有n个格子 for(int k=0;k<j;k++) dp[cur][j][k]=0; // 前前次的结果设为0 // for(int j=1;j<=i;j++){ // 第i步的红色格子数目至多为i个 for(int k=0;k<j;k++){ // if(dp[old][j][k]>0){ // 往右走 int pos1 = j; // 现在有的格子数 int pos2 = k+1; // 现在的位置是在k+1 if(pos1==pos2) // 在有边界的条件,接下来右边会多一个空格的可能。k=j-1时。 ++pos1; // 多一个空格 dp[cur][pos1][pos2]+=0.5*dp[old][j][k]; // 往左走 int pos3 = j; int pos4 = k-1; if(pos4==-1){ // 边界条件,在位置-1的时候 pos3++; // 格子数增加1 pos4++; // 把-1的那个格子记为第0个格子~ } dp[cur][pos3][pos4]+=0.5*dp[old][j][k]; } } } } // 知道概率以后求期望 for(int i=1;i<=n+1;i++){ // 走n步,至多有n+1个格子 for(int j=0;j<i;j++){ // 在第j个格子上 ans+=i*dp[n%2][i][j]; } } DecimalFormat f = new DecimalFormat("0.0"); System.out.print(f.format(ans)); } }
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const ll INF = (ll)inf*inf; const int maxn = 505; double dp[2][maxn][maxn]; int main() { int n;cin>>n; dp[0][1][1]=1.0; int last,now; for(int i=1;i<=n;i++){ last=(i-1)%2; now=i%2; for(int j=1;j<=i+1;j++)for(int k=0;k<=j;k++)dp[now][j][k]=0; for(int j=1;j<=i+1;j++){ for(int k=1;k<=j;k++){ //goto left if(k==1){ dp[now][j+1][k]+=dp[last][j][k]*0.5; } else{ dp[now][j][k-1]+=dp[last][j][k]*0.5; } //goto right if(k==j){ dp[now][j+1][k+1]+=dp[last][j][k]*0.5; } else{ dp[now][j][k+1]+=dp[last][j][k]*0.5; } } } } double ans=0; for(int j=1;j<=n+1;j++){ for(int k=0;k<=j+2;k++){ ans+=j*dp[now][j][k]; } } printf("%.1f\n",ans); return 0; }
varn = parseInt(readline());vardp = newArray(2);varans = 0;for(vari=0; i<2; i++){dp[i]=[];for(varj=0; j<=n+1; j++){dp[i][j]=[];for(vark=0; k<=n+1; k++){dp[i][j][k] = 0;}}}dp[0][1][0] = 1.0;for(vari=1; i<=n; i++){varnow = i%2;varold = 1-(i%2);for(varj=1; j<=i; j++){for(vark=0; k<j; k++){dp[now][j][k]=0;}}for(varj=1; j<=i; j++){for(vark=0; k<j; k++){if(dp[old][j][k]>0){// 往右走varpos1 = j;varpos2 = k+1;if(pos1==pos2){pos1++;}dp[now][pos1][pos2]+=0.5*dp[old][j][k];// 往左走varpos3 = j;varpos4 = k-1;if(pos4==-1){pos3++;pos4++;}dp[now][pos3][pos4]+=0.5*dp[old][j][k];}}}}for(varj=1; j<=n+1; j++){for(vark=0; k<j;k++){ans+=j*dp[n%2][j][k];}}print(ans.toFixed(1));
//利用仿真思想实习,会有一点点偏差
#include <iomanip>
//http://blog.csdn.net/xiaxzhou/article/details/73382283
//↑↑↑大佬的思路↑↑↑#include<iostream> #include<string> #include<vector> #include <iomanip> using namespace std; double dp[2][502][502] = { 0 }; int main() { int n; double ans = 0; cin >> n; dp[0][1][1] = 1; dp[1][2][1] = 0.5; dp[1][2][2] = 0.5; for (int i = 2; i <= n; i++) { int cur = i & 1; int oth = 1 - cur; for (int j = 0; j <= i+1; j++) for (int k = 0; k <= j; k++) dp[cur][j][k] = 0; for (int j = 1; j <= i+1; j++) { for (int k = 1; k <= j; k++) { if (dp[oth][j][k] == 0) continue; if (k == 1) { dp[cur][j + 1][1] += dp[oth][j][k] / 2; dp[cur][j][2] += dp[oth][j][k] / 2; } else if (k == j) { dp[cur][j + 1][k + 1] += dp[oth][j][k] / 2; dp[cur][j][k - 1] += dp[oth][j][k] / 2; } else { dp[cur][j][k + 1] += dp[oth][j][k] / 2; dp[cur][j][k - 1] += dp[oth][j][k] / 2; } } } } int cur = n & 1; for (int i = 1; i <= n + 1; i++) { double sum = 0; for (int j = 1; j <= i; j++) { sum += dp[cur][i][j]; //cout <<setw(10)<< dp[cur][i][j] <<' '; } ans += i*sum; //cout << endl; } cout <<fixed<< setprecision(1) << ans; //fixed is needed cin >> n; return 0; }