题目链接:http://acm.uestc.edu.cn/#/problem/show/1652
解法:多段图问题,用滚动数组,转移很好想。
概率DP
算法复杂度:O(N*M*log N)
用kk[i]记录第i个障碍物的位置
pos=(b-1)*m+a;
kk[i]=pos;
dp1[j]记录当前所有车道安全的概率
dp2[j]记录下一步所有车道安全的概率
初始化:memset(dp1,0,sizeof(dp1));dp1[p]=1;
for(i=1;i<=n;i++)
{
memset(dp2,0,sizeof(dp2));
for(j=1;j<=m;j++)
{
如果该位置有障碍 dp2[j]=0
否则:
如果m=1 dp2[j]=dp1[j]
否则:
如果j=2 dp2[j]+=dp1[j-1]/2 如果j>2 dp2[j]+=dp1[j-1]/3
如果1
#include <bits/stdc++.h>
using namespace std;
const int maxn = 30010;
int m, k, n, p, a, b, kk[maxn];
double dp1[maxn], dp2[maxn];
double dp[2][maxn];
bool pos[1010][30010];
int now=0,pre=1;
int main()
{
scanf("%d %d %d", &m,&k,&n);
scanf("%d", &p);
bool flag = 1;
for(int i=1; i<=k; i++){
scanf("%d %d", &a,&b);
if(b<=n){
// int pos=(b-1)*m+a;
// kk[i]=pos;
pos[b][a] = 1;
flag = 0;
}
}
if(m == 1){
if(!flag){
puts("0.000000");
}
else{
puts("1.000000");
}
return 0;
}
// memset(dp1,0,sizeof(dp1));
// dp1[p]=1;
// for(int i=1; i<=n; i++){
// memset(dp2,0,sizeof(dp2));
// for(int j=1; j<=m; j++){
// int cur = (i-1)*m+j;
// int pos = upper_bound(kk+1,kk+k+1,cur)-kk;
// pos--;
// if(kk[pos]==cur){
// dp2[j]=0;
// }
// else{
// if(m==1) dp2[j]=dp1[j];
// else{
// if(j==2) dp2[j]+=dp1[j-1]/2;
// if(j>2) dp2[j]+=dp1[j-1]/3;
// if(j>1&&j<m) dp2[j]+=dp1[j]/3;
// if(j==1||j==m) dp2[j]+=dp1[j]/2;
// if(j==m-1) dp2[j]+=dp1[j+1]/2;
// if(j<m-1) dp2[j]+=dp1[j+1]/3;
// }
// }
// }
// for(int j=1; j<=m; j++) dp1[j]=dp2[j];
// }
// double ans=0;
// for(int j=1; j<=m; j++){
// ans+=dp1[j];
// }
// printf("%.6f\n", ans);
dp[now][p]=1;
for(int i=1; i<=n; i++){
swap(now, pre);
memset(dp[now],0,sizeof(dp[now]));
for(int k=1; k<=2; k++){
if(!pos[i-1][1]){
dp[now][k]+=dp[pre][1]/2.0;
}
}
for(int k=m-1; k<=m; k++){
if(!pos[i-1][m]){
dp[now][k]+=dp[pre][m]/2.0;
}
}
for(int j=2; j<m; j++){
for(int k=j-1; k<=j+1; k++){
if(!pos[i-1][j]){
dp[now][k]+=dp[pre][j]/3.0;
}
}
}
}
double ans=0;
for(int j=1; j<=m; j++){
if(!pos[n][j]){
ans+=dp[now][j];
}
}
printf("%.6f\n", ans);
return 0;
}