【Luogu】P2489迷宫探险(概率DP)

  题目链接

  设f[i][j][k][l]是当前在(i,j),对陷阱的了解状态为k(0表示了解该陷阱为无危险,1表示了解该陷阱有危险,2不了解),l表示当前血,走出迷宫的概率

  dfsDP即可。  注意随时更新和细节。

#include<cstdio>
#include<cstdlib>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 200
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

int u[5]={0,1,0,-1,0};
int w[5]={0,0,-1,0,1};

char mp[maxn][maxn];

double p[maxn];
double g[maxn*10][maxn];
int pw[maxn];

int n,m,e,h;

int getlens(int x,int len){    return x/pw[len-1]%3;    }

double f[50][50][maxn*10][10];
bool vis[50][50][maxn*10][10];

int chan(int x,int len,int nu){
    return x-getlens(x,len)*pw[len-1]+nu*pw[len-1];
}

void dfs(int x,int y,int state,int blo){
    //printf("%d %d\n",x,y);
    //printf("%d %d %d %d %.3lf\n",x,y,state,blo,f[x][y][state][blo]);
    if(vis[x][y][state][blo])    return;
    if(mp[x][y]=='@'){    f[x][y][state][blo]=1;    vis[x][y][state][blo]=1;    return;    }
    if(blo==0){    f[x][y][state][blo]=0;    vis[x][y][state][blo]=1;    return;    }
    vis[x][y][state][blo]=1;
    double &ans=f[x][y][state][blo];
    for(int i=1;i<5;++i){
        int nx=x+u[i],ny=y+w[i];
        if(nx<1||nx>n||ny<1||ny>m||mp[nx][ny]=='#')    continue;
        char c=mp[nx][ny];
        int now=c-'A'+1;
        if(c=='.'||c=='$'||c=='@'||(now>=1&&now<=e&&getlens(state,now)==0)){
            dfs(nx,ny,state,blo);
            ans=max(ans,f[nx][ny][state][blo]);
        }
        //if(now<1||now>e)    continue;
        if(now>=1&&now<=e&&getlens(state,now)==1){
            dfs(nx,ny,state,blo-1);
            ans=max(ans,f[nx][ny][state][blo-1]);
        }
        if(now>=1&&now<=e&&getlens(state,now)==2){
            int sta=chan(state,now,1);
            int stb=chan(state,now,0);
            dfs(nx,ny,sta,blo-1);
            dfs(nx,ny,stb,blo);
            
            ans=max(ans,g[state][now]*f[nx][ny][sta][blo-1]+(1.0-g[state][now])*f[nx][ny][stb][blo]);
        }
    }
    f[x][y][state][blo]=ans;
    return;
}

int main(){
    int sx,sy;
    n=read(),m=read(),e=read(),h=read();
    for(int i=1;i<=n;++i){
        scanf("%s",mp[i]+1);
        for(int j=1;j<=m;++j)
            if(mp[i][j]=='$'){
                sx=i;    sy=j;
            }
    }
    for(int i=0;i<(1<<e);++i)    p[i]=read();
    int Max=0;pw[0]=1;
    for(int i=1;i<=e;++i)    pw[i]=pw[i-1]*3;
    //printf("%d",Max);
    for(int i=0;i<=pw[e];++i){
        int sum=0;
        for(int j=0;j<(1<<e);++j){
            bool flag=0;
            for(int k=1;k<=e;++k){
                int now=getlens(i,k),ret=(j>>k-1)&1;
                if(now==2)    continue;
                if(now!=ret){
                    flag=1;
                    break;
                }
            }
            if(flag)    continue;
            sum+=p[j];
            for(int k=1;k<=e;++k){
                if(getlens(i,k)!=2||((j>>k-1)&1)==0)    continue;
                g[i][k]+=p[j];
            }
        }
        for(int j=1;j<=e;++j)    g[i][j]/=sum;
    }
    
    dfs(sx,sy,pw[e]-1,h);
    printf("%.3lf",f[sx][sy][pw[e]-1][h]);
    return 0;
}

 

posted @ 2018-04-25 19:52  Konoset  阅读(212)  评论(0编辑  收藏  举报