zoukankan      html  css  js  c++  java
  • BZOJ 2246 [SDOI2011]迷宫探险 (记忆化搜索)

    题目大意:太长了,略

    bzoj luogu

    并没有想到三进制状压

    题解:

    3进制状压陷阱的状态,0表示这种陷阱的状态未知,1已知危险,2已知不危险

    然后预处理出在当前状态下,每种陷阱有害的概率,设为$g[s][i]$

    已知是危险的,有害概率为1

    已知是不危险的,有害概率为0

    未知的部分用概率表格里符合当前状态的部分,才是正确的(比如第4个样例输出了0.857就是没用这种方法去求概率)

    定义$f[x][y][s][h]$表示当前在(x,y),陷阱的状态为s,当前血量是h

    然后记忆化爆搜即可

    ...

    此题解针对在luogu上交了,WA了第2个/第8个/第10个点,然后“换了个枚举顺序”就恰好A掉了这道题的情况

    仔细观察发现上面那种做法貌似是有一些问题的

    比如从上一层xxxx往下走↓,走到了yyyy这个状态,然后,yyyy还会往上跑从xxxx更新,得到了一个#$%@的“最优解”,这可能是yyyy往上跑的最优解,但也可能不是!

    因为你状态xxxx可能还有某个方向没有遍历,但我们草率得把f[xxxx]这个“并不最优解”去更新f[yyyy]

    那如果在另一次搜索中,由某个状态zzzz往上走↑,又跑到了yyyy,由于访问过了yyyy,所以返回了f[yyyy],然而这个f[yyyy]可能并不是最优解,导致答案出错!

    为了避免这种错误,我们额外记录一维,表示从那个方向跑到当前状态,$f[x][y][s][h][t]$,t表示上一层是从哪个方向来的即可,虽然牺牲了一些常数但保证了答案的正确性!

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #define N 35
      5 #define M 250
      6 #define dd double
      7 #define idx(x) (x-'A'+1)
      8 using namespace std;
      9 
     10 int n,m,sx,sy,K,H;
     11 char str[N][N];
     12 int xx[]={-1,0,1,0},yy[]={0,1,0,-1};
     13 int pw[]={1,3,9,27,81,243,729};
     14 int mp[N][N],pro[M];
     15 dd f[N][N][M][7][5],g[M][7],dan[7];
     16 bool vis[N][N][M][7][5];
     17 bool check(int x,int y){
     18     if(x<1||x>n||y<1||y>m||mp[x][y]==-1) return 0;
     19     else return 1;}
     20 int p[M][7];
     21 dd dfs(int x,int y,int s,int h,int fa)
     22 {
     23     if(h<=0) return 0;
     24     if(vis[x][y][s][h][fa]) return f[x][y][s][h][fa];
     25     vis[x][y][s][h][fa]=1;
     26     if(mp[x][y]==K+1){
     27         f[x][y][s][h][fa]=1;
     28         return 1;
     29     }int tx,ty,t1,t2,pt;
     30     dd tmp=0;
     31     for(int i=0;i<4;i++)
     32     {
     33         tx=x+xx[i],ty=y+yy[i];
     34         if(!check(tx,ty)) continue;
     35         pt=mp[tx][ty],t1=t2=s;
     36         dd ans1=0,ans2=0;
     37         if(pt>0&&pt<=K&&!p[s][pt]) t1+=(1*pw[pt-1]);
     38         if(pt>0&&pt<=K&&!p[s][pt]) t2+=(2*pw[pt-1]);
     39         if(pt!=-1){
     40             if(g[s][pt]>0.0&&h>1) ans1=dfs(tx,ty,t1,h-1,(i+2)%4);
     41             if(g[s][pt]<1.0)ans2=dfs(tx,ty,t2,h,(i+2)%4);
     42             tmp=max(tmp,1.0*g[s][pt]*ans1+(1.0-g[s][pt])*ans2);
     43         }
     44     }f[x][y][s][h][fa]=tmp;
     45     return f[x][y][s][h][fa];
     46 }
     47 void Pre()
     48 {
     49     for(int i=0;i<(1<<K);i++)
     50         scanf("%d",&pro[i]);
     51     for(int i=0;i<pw[K];i++){
     52         int x=i,k=K;
     53         while(k){
     54             p[i][k]=x/pw[k-1];
     55             x%=pw[k-1],k--;}
     56     }
     57     for(int i=0;i<pw[K];i++)
     58     {
     59         int tot=0,sum;
     60         for(int j=0;j<K;j++)
     61             dan[j+1]=0;
     62         for(int s=0;s<(1<<K);s++){
     63             int fl=1;
     64             for(int j=0;j<K;j++)
     65                 if((s&(1<<j))&&p[i][j+1]==2) {fl=0;break;} 
     66                 else if((!(s&(1<<j)))&&p[i][j+1]==1) {fl=0;break;}
     67             if(!fl) continue;
     68             tot+=pro[s];
     69         }int x=i,k=K;
     70         for(int k=1;k<=K;k++)
     71         {
     72             if(p[i][k]==0){
     73                 sum=0;
     74                 for(int s=0;s<(1<<K);s++)
     75                 {
     76                     int fl=1;
     77                     for(int j=0;j<K;j++)
     78                         if((s&(1<<j))&&p[i][j+1]==2) {fl=0;break;} 
     79                         else if((!(s&(1<<j)))&&p[i][j+1]==1) {fl=0;break;}
     80                     if(!fl) continue;
     81                     if(s&(1<<(k-1))) sum+=pro[s];
     82                 }g[i][k]=1.0*sum/tot;
     83             }
     84             if(p[i][k]==1){g[i][k]=1.0;}
     85             if(p[i][k]==2){g[i][k]=0.0;}
     86         }
     87     }
     88 }
     89 int main()
     90 {
     91     scanf("%d%d%d%d",&n,&m,&K,&H);
     92     for(int i=1;i<=n;i++){
     93         scanf("%s",str[i]+1);
     94         for(int j=1;j<=m;j++)
     95         if(str[i][j]=='$') sx=i,sy=j;
     96         else if(str[i][j]=='@') mp[i][j]=K+1;
     97         else if(str[i][j]=='#') mp[i][j]=-1;
     98         else if(str[i][j]=='.') mp[i][j]=0;
     99         else mp[i][j]=idx(str[i][j]);
    100     }
    101     Pre();
    102     printf("%.3lf
    ",dfs(sx,sy,0,H,4));
    103     return 0;
    104 }
  • 相关阅读:
    Spherical Harmonic Lighting
    EV/ISO/Stop
    opengles dither
    rgb颜色空间到xyz空间的映射
    LUT color grading
    tonemapping
    ue4 sequencer
    pbr -physical based rendering
    BRDF
    /sockjs-node/info 报错问题
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9958410.html
Copyright © 2011-2022 走看看