hdu 2262 Where is the canteen http://acm.hdu.edu.cn/showproblem.php?pid=2262 2013-1-20
期望。每个点列出一个方程,高斯消元求解

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int N=20; 7 const int dx[]={1,0,-1,0}; 8 const int dy[]={0,1,0,-1}; 9 const double eps=1e-8; 10 char mz[N][N]; 11 double dp[N*N],mt[N*N][N*N],ans[N*N]; 12 int dcmp(double x) 13 { 14 return x<-eps?-1:x>eps; 15 } 16 void getmt(int n,int m) 17 { 18 for(int x=0;x<n;x++) 19 for(int y=0;y<m;y++) 20 { 21 int r=x*m+y; 22 if(mz[x][y]=='#') continue; 23 if(mz[x][y]=='$') {mt[r][r]=1; continue;} 24 int cnt=0; 25 for(int d=0;d<4;d++) 26 { 27 int nx=x+dx[d],ny=y+dy[d]; 28 if(nx>=0 && nx<n && ny>=0 && ny<m && mz[nx][ny]!='#') cnt++; 29 } 30 if(cnt>0) 31 { 32 mt[r][r]=mt[r][n*m]=1; 33 for(int d=0;d<4;d++) 34 { 35 int nx=x+dx[d],ny=y+dy[d]; 36 if(nx>=0 && nx<n && ny>=0 && ny<m && mz[nx][ny]!='#') 37 mt[r][nx*m+ny]=-1.0/cnt; 38 } 39 } 40 } 41 } 42 void gauss(int n,int m) 43 { 44 for(int r=0,c=0;r<n && c<m;r++,c++) 45 { 46 int p=r; 47 while(p<n && dcmp(mt[p][c])==0) p++; 48 if(p==n) {r--; continue;} 49 if(p!=r) for(int i=c;i<=m;i++) 50 swap(mt[p][i],mt[r][i]); 51 for(int i=0;i<n;i++) 52 if(i!=r && mt[i][c]!=0) 53 { 54 double t=mt[i][c]/mt[r][c]; 55 for(int j=c;j<=m;j++) 56 mt[i][j]-=mt[r][j]*t; 57 } 58 } 59 for(int i=0;i<n;i++) 60 { 61 int p=-1,cnt=0; 62 for(int j=i;j<m;j++) if(dcmp(mt[i][j])!=0) 63 { 64 p=j; 65 cnt++; 66 } 67 if(cnt==1) ans[p]=mt[i][m]/mt[i][p]; 68 } 69 } 70 int main() 71 { 72 int n,m; 73 while(~scanf("%d%d",&n,&m)) 74 { 75 for(int i=0;i<n;i++) scanf("%s",mz[i]); 76 memset(mt,0,sizeof(mt)); 77 memset(ans,0,sizeof(ans)); 78 getmt(n,m); 79 gauss(n*m,n*m); 80 double s; 81 for(int x=0;x<n;x++) 82 for(int y=0;y<m;y++) 83 if(mz[x][y]=='@') s=ans[x*m+y]; 84 if(dcmp(s)>0) printf("%lf\n",s); 85 else printf("-1\n"); 86 } 87 return 0; 88 }
hdu 4089 Activation http://acm.hdu.edu.cn/showproblem.php?pid=4089 2013-1-19
求概率,跟求期望差不多,有环。
求dp[i]时要把dp[i-1]看成常数

1 #include <cstdio> 2 using namespace std; 3 4 const int N=2010; 5 double dp[N][N],c[N]; 6 int main() 7 { 8 int n,m,k; 9 double p1,p2,p3,p4; 10 while(~scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)) 11 { 12 if(1-p1-p2<1e-8) 13 { 14 printf("%.5lf\n",0); 15 continue; 16 } 17 dp[1][1]=p4/(1-p1-p2); 18 double q2=p2/(1-p1); 19 double q3=p3/(1-p1); 20 double q4=p4/(1-p1); 21 for(int i=2;i<=n;i++) 22 { 23 c[1]=q4; 24 for(int j=2;j<=i;j++) 25 { 26 if(j<=k) c[j]=dp[i-1][j-1]*q3+q4; 27 else c[j]=dp[i-1][j-1]*q3; 28 } 29 double sq=1,sc=0; 30 for(int j=2;j<=i;j++) 31 { 32 sq=sq*q2; 33 sc=sc*q2+c[j]; 34 } 35 sq*=q2; sc=sc*q2+c[1]; 36 dp[i][1]=sc/(1-sq); 37 for(int j=2;j<=i;j++) 38 dp[i][j]=dp[i][j-1]*q2+c[j]; 39 } 40 printf("%.5lf\n",dp[n][m]); 41 } 42 return 0; 43 }
hdu 3853 LOOPS http://acm.hdu.edu.cn/showproblem.php?pid=3853 2013-1-18
求步数的期望
dp[i][j]=(dp[i][j+1]*p[i][j][1]+dp[i+1][j]*p[i][j][2]+dp[i][j]*p[i][j][0])+2
dp[i][j]=(dp[i][j+1]*p[i][j][1]+dp[i+1][j]*p[i][j][2]+2)/(1-p[i][j][0])
避免被0除,可能存在走不到p[i][j][0]=1的点

1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 5 const int N=1010; 6 const double INF=1e10; 7 double dp[N][N],p[N][N][3]; 8 int main() 9 { 10 int n,m; 11 while(~scanf("%d%d",&n,&m)) 12 { 13 for(int i=1;i<=n;i++) 14 for(int j=1;j<=m;j++) 15 for(int k=0;k<3;k++) scanf("%lf",&p[i][j][k]); 16 for(int i=n;i>0;i--) 17 for(int j=m;j>0;j--) 18 { 19 if(i==n && j==m) dp[i][j]=0; 20 else if(p[i][j][0]==1) dp[i][j]=INF; 21 else dp[i][j]=(dp[i][j+1]*p[i][j][1]+dp[i+1][j]*p[i][j][2]+2)/(1-p[i][j][0]); 22 } 23 printf("%.3lf\n",dp[1][1]); 24 } 25 return 0; 26 }
hdu 4405 Aeroplane chess http://acm.hdu.edu.cn/showproblem.php?pid=4405 2013-1-18
求步数的期望,0出发到n,掷骰子,几点走几步,中间有传送,求掷骰子次数的期望
n到n的期望为0,f(p)=sigma((f(p+k)+1)/6)

1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 5 const int N=100010; 6 double p[N]; 7 int next[N]; 8 int main() 9 { 10 int n,m; 11 while(scanf("%d%d",&n,&m),n||m) 12 { 13 memset(next,-1,sizeof(next)); 14 memset(p,0,sizeof(p)); 15 for(int i=0;i<m;i++) 16 { 17 int u,v; 18 scanf("%d%d",&u,&v); 19 next[u]=v; 20 } 21 for(int u=n-1;u>=0;u--) if(next[u]==-1) 22 { 23 for(int i=1;i<=6;i++) 24 { 25 int v=u+i; 26 if(v>n) v=n; 27 while(next[v]!=-1) v=next[v]; 28 p[u]+=(p[v]+1)/6; 29 } 30 } 31 printf("%.4lf\n",p[0]); 32 } 33 return 0; 34 }
hdu 4487 Maximum Random Walk http://acm.hdu.edu.cn/showproblem.php?pid=4487 2013-1-18
步数一定,求概率,虽然说是求期望,本质是先求各个状态的概率,再算期望

1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 5 const double eps=1e-8; 6 const int N=110; 7 double dp[N][N*2][N]; 8 int main() 9 { 10 int T; 11 scanf("%d",&T); 12 while(T--) 13 { 14 int C; 15 scanf("%d",&C); 16 printf("%d ",C); 17 int n; 18 double pl,pr; 19 scanf("%d%lf%lf",&n,&pl,&pr); 20 memset(dp,0,sizeof(dp)); 21 dp[0][n][n]=1; 22 for(int i=0;i<n;i++) 23 for(int j=0;j<=n*2;j++) 24 for(int k=j;k<=n*2;k++) if(dp[i][j][k]>0) 25 { 26 dp[i+1][j][k]+=dp[i][j][k]*(1-pl-pr); 27 dp[i+1][j-1][k]+=dp[i][j][k]*pl; 28 if(j+1>k) dp[i+1][j+1][k+1]+=dp[i][j][k]*pr; 29 else dp[i+1][j+1][k]+=dp[i][j][k]*pr; 30 } 31 double ans=0; 32 for(int j=0;j<=n*2;j++) 33 for(int k=j;k<=n*2;k++) ans+=dp[n][j][k]*(k-n); 34 printf("%.4lf\n",ans); 35 } 36 return 0; 37 }