UESTC 1652 都市大飙车

来源:互联网 发布:青岛太阳软件拖欠工资 编辑:程序博客网 时间:2024/04/28 02:56

题目链接: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;}
原创粉丝点击