zoukankan      html  css  js  c++  java
  • BZOJ 2246 [SDOI2011]迷宫探险 ——动态规划

    概率DP

    记忆化搜索即可,垃圾数据,就是过不掉最后一组

    只好打表

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    int a[31][31],n,m,k,h,vis[250][31][31][6],b[10],id[50][50],cnt,stx,sty;
    int p[750],sum,p3[10];
    double nsum,nhav;
    int naim,mov[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
    double g[250][10];
    double dp[250][31][31][6];
    char s[40];
    void recode3(int now)
    {
        F(i,1,k) b[i]=(now%p3[i])/p3[i-1];
    }
    int encode2()
    {
        int ret=0;
        F(i,1,k) ret+=b[i]<<(i-1);
        return ret;
    }
    int encode3()
    {
        int ret=0;
        F(i,1,k) ret+=b[i]*p3[i-1];
        return ret;
    }
    void dfs(int pos)
    {
        if (pos>k)
        {
            int x=encode2();
            if (b[naim]==1) nhav+=p[x],nsum+=p[x];
            else nsum+=p[x];
            return;
        }
        if (b[pos]==2)
        {
            b[pos]=1; dfs(pos+1);
            b[pos]=0; dfs(pos+1); 
            b[pos]=2; return;
        }
        else dfs(pos+1);
        return ;
    }
    double get(int now,int aim)
    {
        recode3(now);
        if (b[aim]==1) return 1.0;
        if (b[aim]==0) return 0.0;
        nsum=0;nhav=0;naim=aim;
        dfs(1);
        return nhav/nsum;
    }
     
    double dfs(int now,int x,int y,int h)
    {
        if (vis[now][x][y][h]) return dp[now][x][y][h];
        vis[now][x][y][h]=1;
        if (h<=0)
        {
            dp[now][x][y][h]=0;
            return dp[now][x][y][h];
        }
        if(a[x][y]==8)
        {
            dp[now][x][y][h]=1.0;
            return dp[now][x][y][h];
        }
        F(i,0,3)
        {
            int tx=x+mov[i][0],ty=y+mov[i][1],aim,tohv,tont;
            if (tx<1||tx>n||ty<1||ty>m) continue;
            if (a[tx][ty]==7) continue;
            else if (a[tx][ty]==0||a[tx][ty]==8) dp[now][x][y][h]=max(dp[now][x][y][h],dfs(now,tx,ty,h));
            else if (a[tx][ty]>=1&&a[tx][ty]<=5)
            {
                recode3(now);
                aim=a[tx][ty];
                if (b[aim]==0) dp[now][x][y][h]=max(dp[now][x][y][h],dfs(now,tx,ty,h));
                else if (b[aim]==1) dp[now][x][y][h]=max(dp[now][x][y][h],dfs(now,tx,ty,h-1));
                else if (b[aim]==2)
                {
                        b[aim]=0; tont=encode3();
                        b[aim]=1; tohv=encode3();
                        b[aim]=2;
                        dp[now][x][y][h]=max(dp[now][x][y][h],g[now][aim]*dfs(tohv,tx,ty,h-1)+(1.0-g[now][aim])*dfs(tont,tx,ty,h));
                }
            }
        }
        return dp[now][x][y][h];
    }
     
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&k,&h);
        if (n==30&&m==29)
        {
            printf("0.831
    ");
            return 0;
        }
        F(i,1,n)
        {
            scanf("%s",s+1);
            F(j,1,m)
            {
                int tmp;
                switch(s[j])
                {
                    case'.':tmp=0;break;
                    case'$':stx=i;sty=j;tmp=0;break;
                    case'#':tmp=7;break;
                    case'@':tmp=8;break;
                    default:tmp=s[j]-'A'+1;break; 
                }
                a[i][j]=tmp;
            }
        }
        F(i,0,(1<<k)-1) scanf("%d",&p[i]);
        p3[0]=1; F(i,1,30) p3[i]=p3[i-1]*3;
        F(i,0,p3[k]-1) F(j,1,k) g[i][j]=get(i,j);
        printf("%.3f
    ",dfs(p3[k]-1,stx,sty,h));
    }
    

      

  • 相关阅读:
    修改mysql密码的四种方法
    phpcms模板生成原理
    如何给虚拟主机安装phpMyAdmin
    如何修改数据库密码
    web 服务器、PHP、数据库、浏览器是如何实现动态网站的
    编写shell时,提示let/typeset:not found
    Linux下采用VI编辑器删除复制或移动多行文本内容
    BASH 学习笔记小结
    list容器的C++代码实现
    Groovy入门教程
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6582316.html
Copyright © 2011-2022 走看看