題目大意:
開始位置在0,每一步可以向右向左或者不動,問走了n步後,路徑中能到達最右的期望。
解題思路:
比賽的時候,題目理解錯了,認為要回到起點。-_- -_-
由於最後到達的位置不確定,每條路徑的最右距離也不確定。
所以記dp[i][j][k]為走了i步,到達j位置,且路徑中最右位置為k時概率。
顯然k>=j 否則為0
如果k==j,這一步有兩種情況,1、剛好第一次達到最大 2、先前已經達到了最大。注意此時不能從右邊向左過來,超過了k.
如果k>j ,說明這一步沒有到達k,只能是前面的已經到達了k.
s為不動的概率,r,l分別為向右走和向左走的概率。
記開始的位置為100.
代碼:
<SPAN style="FONT-SIZE: 18px">#include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #define eps 1e-6 #define INF 0x1f1f1f1f #define PI acos(-1.0) #define ll __int64 #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; /* freopen("data.in","r",stdin); freopen("data.out","w",stdout); */ #define N 110 double dp[2][N*2][N*2]; //dp[][i][j]表示走到當前步,到達i,最右的位置為j的概率 int main() { int t,d,n; double l,r,s; scanf("%d",&t); while(t--) { scanf("%d%d%lf%lf",&d,&n,&l,&r); s=1-l-r; memset(dp,0,sizeof(dp)); dp[0][100][100]=1; //初始化最開始的位置 int la=0,cur; for(int i=1;i<=n;i++) { cur=la^1; for(int j=100-i;j<=100+i;j++) { for(int k=max(100,j);k<=200;k++) //k肯定要>=j,第一步在100無論怎麼走最右肯定大於等100 { if(k==j) //這一步到了最右 dp[cur][j][k]=dp[la][j][k]*s+dp[la][j-1][k-1]*r+dp[la][j-1][k]*r; else //k>j的情況 之前已經到達了最大k dp[cur][j][k]=dp[la][j][k]*s+dp[la][j-1][k]*r+dp[la][j+1][k]*l; } } la=cur; } double ans=0; for(int i=(100-n);i<=100+n;i++) for(int j=100;j<=100+n;j++) ans=ans+dp[cur][i][j]*(j-100); //直接求期望 printf("%d %.4lf\n",d,ans); } return 0; } </SPAN>