BZOJ 2246 [SDOI2011]迷宫探险 (记忆化搜索)
题目大意:太长了,略
并没有想到三进制状压
题解:
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]迷宫探险 (记忆化搜索)的更多相关文章
- BZOJ 2246 [SDOI2011]迷宫探险 ——动态规划
概率DP 记忆化搜索即可,垃圾数据,就是过不掉最后一组 只好打表 #include <cstdio> #include <cstring> #include <iostr ...
- BZOJ.2246.[SDOI2011]迷宫探险(DP 记忆化搜索 概率)
题目链接 求最大的存活概率,DP+记忆化. 用f[s][x][y][hp]表示在s状态,(x,y)点,血量为hp时的存活概率. s是个三进制数,记录每个陷阱无害/有害/未知. 转移时比较容易,主要是在 ...
- [BZOJ 1068] [SCOI2007] 压缩 【记忆化搜索】
题目链接:BZOJ - 1068 题目分析 这种记忆化搜索(区间 DP) 之前就做过类似的,也是字符串压缩问题,不过这道题稍微复杂一些. 需要注意如果某一段是 S1S1 重复,那么可以变成 M + S ...
- BZOJ 1079: [SCOI2008]着色方案 记忆化搜索
1079: [SCOI2008]着色方案 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...
- 【BZOJ2246】[SDOI2011]迷宫探险(搜索,动态规划)
[BZOJ2246][SDOI2011]迷宫探险(搜索,动态规划) 题面 BZOJ 洛谷 题解 乍一看似乎是可以求出每个东西是陷阱的概率,然而会发现前面走过的陷阱是不是陷阱实际上是会对当前状态产生影响 ...
- [BZOJ 1048] [HAOI2007] 分割矩阵 【记忆化搜索】
题目链接:BZOJ - 1048 题目分析 感觉这种分割矩阵之类的题目很多都是这样子的. 方差中用到的平均数是可以直接算出来的,然后记忆化搜索 Solve(x, xx, y, yy, k) 表示横坐标 ...
- [BZOJ 1055] [HAOI2008] 玩具取名 【记忆化搜索】
题目链接:BZOJ - 1055 题目分析 这种类似区间 DP 的记忆化搜索都是很相近的,比如字符串压缩和字符串扩展都差不多. 都是将现在 Solve 的区间分成子区间,再求解子区间. 这道题 Sol ...
- [Swust OJ 409]--小鼠迷宫问题(BFS+记忆化搜索)
题目链接:http://acm.swust.edu.cn/problem/409/ Time limit(ms): 1000 Memory limit(kb): 65535 Description ...
- BZOJ 3895 3895: 取石子 / Luogu SP9934 ALICE - Alice and Bob (博弈 记忆化搜索)
转自PoPoQQQ大佬博客 题目大意:给定n堆石子,两人轮流操作,每个人可以合并两堆石子或拿走一个石子,不能操作者输,问是否先手必胜 直接想很难搞,我们不妨来考虑一个特殊情况 假设每堆石子的数量都&g ...
随机推荐
- MyEclipse如何设置自动提示?
MyEclipse --> Preferences --> Java --> Editor --> Content Assist --> Enable auto acti ...
- jquery获取自定义属性的值
//获取属性值 1 <div id="text" value="黑哒哒的盟友"><div> jQuery取值: $("#tex ...
- day06-2 基本运算符(解压缩)
目录 运算符 算数运算符 比较运算符 赋值运算符 逻辑运算符 运算规则 成员运算符 身份运算符 Python运算符优先级 链式赋值(必考) 交叉赋值(必考) 解压缩(必考) 运算符 算数运算符 进行算 ...
- C语言基本语法——预处理器和预处理指令
1.什么是预处理器 2.什么是预处理器指令 3.预处理器指令 4.宏指令 5.宏函数 6.宏函数的优缺点 7.条件编译指令 1.什么是预处理器 • 预处理器是一个程序,用来处理源程序中的预处理指令. ...
- Github添加SSHkey
Git详细教程可参考廖雪峰的Git教程 1. 打开 Git Bash,输入cd ~/.ssh——回车(看你是否有了ssh key 密钥,有了就备份): 2. 输入ssh-keygen -t rsa - ...
- [CodeForces]1006F Xor Path
双向搜索. 水div3的时候最后一道题由于C题死活看不懂题 来不及做F了Orz.. 因为n,m是20,双向搜索一下,求个到中间的Xor值的方案,统计一下即可. 时间复杂度\(O(2^{21})\) 好 ...
- Golang-import-introduce
本文主要讲解golang中import关键字的用法 import( "fmt" ) //然后在代码里面可以通过如下的方式调用 fmt.Println("hello wor ...
- Mysql学习总结(34)——Mysql 彻底解决中文乱码的问题
mysql 中常常出现对中文支持不友好的情况 常见的错误 "Illegal mix of collations for operation" 下面我们规整一下 mysql 数据库中 ...
- Xshell 安装 Xftp
一.下载 Xftp 链接:https://pan.baidu.com/s/1dGeL2gD 密码:as9x 二.安装 Xftp 无脑下一步 三.点击 Xshell 上的新建文件传输 四.弹出 xftp ...
- HDU 4334 Contest 4
本来以为是一道水题,好吧,做了才知道,出题的人有多牛.二分搜索是不可能的了,因为会超内存... 看到别人的搜索两个集合的提示,我就自己一边去想了.终于想出来了: 可以这样做,先把每两个集合的和值枚举出 ...