题目大意:太长了,略

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表示上一层是从哪个方向来的即可,虽然牺牲了一些常数但保证了答案的正确性!

 #include <cstdio>
#include <cstring>
#include <algorithm>
#define N 35
#define M 250
#define dd double
#define idx(x) (x-'A'+1)
using namespace std; int n,m,sx,sy,K,H;
char str[N][N];
int xx[]={-,,,},yy[]={,,,-};
int pw[]={,,,,,,};
int mp[N][N],pro[M];
dd f[N][N][M][][5],g[M][],dan[];
bool vis[N][N][M][][];
bool check(int x,int y){
if(x<||x>n||y<||y>m||mp[x][y]==-) return ;
else return ;}
int p[M][];
dd dfs(int x,int y,int s,int h,int fa)
{
if(h<=) return ;
if(vis[x][y][s][h][fa]) return f[x][y][s][h][fa];
vis[x][y][s][h][fa]=;
if(mp[x][y]==K+){
f[x][y][s][h][fa]=;
return ;
}int tx,ty,t1,t2,pt;
dd tmp=;
for(int i=;i<;i++)
{
tx=x+xx[i],ty=y+yy[i];
if(!check(tx,ty)) continue;
pt=mp[tx][ty],t1=t2=s;
dd ans1=,ans2=;
if(pt>&&pt<=K&&!p[s][pt]) t1+=(*pw[pt-]);
if(pt>&&pt<=K&&!p[s][pt]) t2+=(*pw[pt-]);
if(pt!=-){
if(g[s][pt]>0.0&&h>) ans1=dfs(tx,ty,t1,h-,(i+)%);
if(g[s][pt]<1.0)ans2=dfs(tx,ty,t2,h,(i+)%);
tmp=max(tmp,1.0*g[s][pt]*ans1+(1.0-g[s][pt])*ans2);
}
}f[x][y][s][h][fa]=tmp;
return f[x][y][s][h][fa];
}
void Pre()
{
for(int i=;i<(<<K);i++)
scanf("%d",&pro[i]);
for(int i=;i<pw[K];i++){
int x=i,k=K;
while(k){
p[i][k]=x/pw[k-];
x%=pw[k-],k--;}
}
for(int i=;i<pw[K];i++)
{
int tot=,sum;
for(int j=;j<K;j++)
dan[j+]=;
for(int s=;s<(<<K);s++){
int fl=;
for(int j=;j<K;j++)
if((s&(<<j))&&p[i][j+]==) {fl=;break;}
else if((!(s&(<<j)))&&p[i][j+]==) {fl=;break;}
if(!fl) continue;
tot+=pro[s];
}int x=i,k=K;
for(int k=;k<=K;k++)
{
if(p[i][k]==){
sum=;
for(int s=;s<(<<K);s++)
{
int fl=;
for(int j=;j<K;j++)
if((s&(<<j))&&p[i][j+]==) {fl=;break;}
else if((!(s&(<<j)))&&p[i][j+]==) {fl=;break;}
if(!fl) continue;
if(s&(<<(k-))) sum+=pro[s];
}g[i][k]=1.0*sum/tot;
}
if(p[i][k]==){g[i][k]=1.0;}
if(p[i][k]==){g[i][k]=0.0;}
}
}
}
int main()
{
scanf("%d%d%d%d",&n,&m,&K,&H);
for(int i=;i<=n;i++){
scanf("%s",str[i]+);
for(int j=;j<=m;j++)
if(str[i][j]=='$') sx=i,sy=j;
else if(str[i][j]=='@') mp[i][j]=K+;
else if(str[i][j]=='#') mp[i][j]=-;
else if(str[i][j]=='.') mp[i][j]=;
else mp[i][j]=idx(str[i][j]);
}
Pre();
printf("%.3lf\n",dfs(sx,sy,,H,));
return ;
}

BZOJ 2246 [SDOI2011]迷宫探险 (记忆化搜索)的更多相关文章

  1. BZOJ 2246 [SDOI2011]迷宫探险 ——动态规划

    概率DP 记忆化搜索即可,垃圾数据,就是过不掉最后一组 只好打表 #include <cstdio> #include <cstring> #include <iostr ...

  2. BZOJ.2246.[SDOI2011]迷宫探险(DP 记忆化搜索 概率)

    题目链接 求最大的存活概率,DP+记忆化. 用f[s][x][y][hp]表示在s状态,(x,y)点,血量为hp时的存活概率. s是个三进制数,记录每个陷阱无害/有害/未知. 转移时比较容易,主要是在 ...

  3. [BZOJ 1068] [SCOI2007] 压缩 【记忆化搜索】

    题目链接:BZOJ - 1068 题目分析 这种记忆化搜索(区间 DP) 之前就做过类似的,也是字符串压缩问题,不过这道题稍微复杂一些. 需要注意如果某一段是 S1S1 重复,那么可以变成 M + S ...

  4. BZOJ 1079: [SCOI2008]着色方案 记忆化搜索

    1079: [SCOI2008]着色方案 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...

  5. 【BZOJ2246】[SDOI2011]迷宫探险(搜索,动态规划)

    [BZOJ2246][SDOI2011]迷宫探险(搜索,动态规划) 题面 BZOJ 洛谷 题解 乍一看似乎是可以求出每个东西是陷阱的概率,然而会发现前面走过的陷阱是不是陷阱实际上是会对当前状态产生影响 ...

  6. [BZOJ 1048] [HAOI2007] 分割矩阵 【记忆化搜索】

    题目链接:BZOJ - 1048 题目分析 感觉这种分割矩阵之类的题目很多都是这样子的. 方差中用到的平均数是可以直接算出来的,然后记忆化搜索 Solve(x, xx, y, yy, k) 表示横坐标 ...

  7. [BZOJ 1055] [HAOI2008] 玩具取名 【记忆化搜索】

    题目链接:BZOJ - 1055 题目分析 这种类似区间 DP 的记忆化搜索都是很相近的,比如字符串压缩和字符串扩展都差不多. 都是将现在 Solve 的区间分成子区间,再求解子区间. 这道题 Sol ...

  8. [Swust OJ 409]--小鼠迷宫问题(BFS+记忆化搜索)

    题目链接:http://acm.swust.edu.cn/problem/409/ Time limit(ms): 1000 Memory limit(kb): 65535   Description ...

  9. BZOJ 3895 3895: 取石子 / Luogu SP9934 ALICE - Alice and Bob (博弈 记忆化搜索)

    转自PoPoQQQ大佬博客 题目大意:给定n堆石子,两人轮流操作,每个人可以合并两堆石子或拿走一个石子,不能操作者输,问是否先手必胜 直接想很难搞,我们不妨来考虑一个特殊情况 假设每堆石子的数量都&g ...

随机推荐

  1. LeetCode Golang 8. 字符串转换整数 (atoi)

    8. 字符串转换整数 (atoi) 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止. 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组 ...

  2. IDEA里面的facets和artifacts的讲解

    Facets: Facets表述了在Module中使用的各种各样的框架.技术和语言.这些Facets让Intellij IDEA知道怎么对待module内容,并保证与相应的框架和语言保持一致. 使用F ...

  3. Day 02 - 02 编程语言的分类

    编程语言的分类 机器语言分为: 1.机器语言 优点:执行代码效率非常快 缺点:开发效率低 2.汇编语言 优点(相对于机器语言):开发效率高 缺点(相对于机器语言):执行效率低 3.高级语言 解释型(同 ...

  4. 从0实现一个React,个人总结

    原文: https://github.com/hujiulong/blog/issues/4 个人总结:: 一.JSX和虚拟DOM import React from 'react'; import ...

  5. 用Arcade表达式添加标签

    Arcade表达式是轻量级的脚本语言,我们可以通过全局变量$feature获取要素属性.比如说,要为城市添加标签,利用CITY_NAME列,我们可以编写语句:$feature.CITY_NAME.Ar ...

  6. 字体样式(.ttf/.woff)文件的配置引入

    在引入前端框架部分功能时,有时需要配置字体样式.可以这样配置:在 .ttf的同级目录下,创建icon.css文件,写入: @font-face {font-family: "element- ...

  7. HDU 1222 Wolf and Rabbit( 简单拓欧 )

    链接:传送门 题意:狼抓兔子,狼从 0 出发沿逆时针寻找兔子,每走一步的距离为 m ,所有洞窟的编号为 0 - n-1 ,问是否存在一个洞窟使得兔子能够安全躲过无数次狼的搜捕. 思路:简单的拓展欧几里 ...

  8. vue自定义一个过滤器

    vue如何自定义一个过滤器 html代码: <div id="app"> <input type="text" v-model="m ...

  9. 【codeforces 812C】Sagheer and Nubian Market

    [题目链接]:http://codeforces.com/contest/812/problem/C [题意] 给你n个物品; 你可以选购k个物品;则 每个物品有一个基础价值; 然后还有一个附加价值; ...

  10. nutch如何修改regex-urlfilter.txt爬取符合条件的链接

    例如我在爬取学生在线的时候,发现爬取不到特定的通知,例如<中粮福临门助学基金申请公告>,通过分析发现原来通知的链接被过滤掉了,下面对过滤url的配置文件regex-urlfilter.tx ...