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

题面

BZOJ

洛谷

题解

乍一看似乎是可以求出每个东西是陷阱的概率,然而会发现前面走过的陷阱是不是陷阱实际上是会对当前状态产生影响的。考虑一下状压,因为出了是陷阱和不是陷阱,还有一种情况是未知。所以三进制状压。

\(0\)表示是有害陷阱,\(1\)表示不是,\(2\)表示未知。

那么假如我们知道了一个当前的三进制状态,如何确定当前的某个未知的陷阱是否有害的概率呢?

这个显然可以暴力提前预处理出来。

那么这就很好办了,设\(f[x][y][hp][S]\)表示当前在\((x,y)\)位置,剩余血量为\(hp\),当前陷阱的状态集合为\(S\)的最大概率。那么直接记忆化爆搜就可以知道结果了。

然而我觉得这个做法是假的,因为你转移的时候可能成环,这也就解释了为什么不按照题解的方向就过不了,然而不这么做还能怎么做啊QwQ。

似乎BZOJ上的数据有锅,怎么交都是T,我蒯别的题解也T了。。。。

然后我改成scanf就WA了,应该数据锅了,到洛谷交吧。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define cmax(a,b) (a=((a)<(b)?(b):(a)))
int bin[]={1,3,9,27,81,243,729,2187,6561};
int let(int x,int k){return x/=bin[k];}
int rit(int x,int k){return x*=bin[k];}
int get(int x,int k){x/=bin[k];return x%3;}
double f[35][35][729][10];
bool vis[35][35][729][10];
int n,m,K,H,P[50];
char g[35][35];
double p[729][10];
int bx,by,ex,ey;
int d[4][2]={1,0,0,-1,-1,0,0,1};
double dfs(int x,int y,int S,int hp)
{
if(vis[x][y][S][hp])return f[x][y][S][hp];
if(!hp)return f[x][y][S][hp]=0;
if(g[x][y]=='@')return f[x][y][S][hp]=1;
vis[x][y][S][hp]=true;
for(int i=0;i<4;++i)
{
int xx=x+d[i][0],yy=y+d[i][1];
if(xx<1||yy<1||xx>n||yy>m)continue;
if(g[xx][yy]=='#')continue;
if(g[xx][yy]>='A'&&g[xx][yy]<='Z')
{
int k=g[xx][yy]-65;
if(get(S,k)<2)//Know
cmax(f[x][y][S][hp],dfs(xx,yy,S,hp-get(S,k)));
else//Unknow
cmax(f[x][y][S][hp],dfs(xx,yy,S-bin[k],hp-1)*p[S][k]+dfs(xx,yy,S-bin[k]*2,hp)*(1-p[S][k]));
}
else
cmax(f[x][y][S][hp],dfs(xx,yy,S,hp));
}
return f[x][y][S][hp];
}
int main()
{
scanf("%d%d%d%d",&n,&m,&K,&H);
for(int i=1;i<=n;++i)scanf("%s",g[i]+1);
for(int i=0;i<1<<K;++i)scanf("%d",&P[i]);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(g[i][j]=='$')bx=i,by=j;
else if(g[i][j]=='@')ex=i,ey=j;
if(!ex){puts("0.000");return 0;}
for(int S=0;S<bin[K];++S)
{
int sumP=0;
for(int i=0;i<1<<K;++i)
{
bool fl=true;
for(int j=0;j<K;++j)
{
int x=get(S,j);if(x==2)continue;
if(((i>>j)&1)!=x){fl=false;break;}
}
if(!fl)continue;
sumP+=P[i];
for(int j=0;j<K;++j)
if(get(S,j)==2&&(i&(1<<j)))p[S][j]+=P[i];
}
for(int j=0;j<K;++j)p[S][j]/=sumP;
}
printf("%.3lf\n",dfs(bx,by,bin[K]-1,H));
return 0;
}

【BZOJ2246】[SDOI2011]迷宫探险(搜索,动态规划)的更多相关文章

  1. BZOJ2246 [SDOI2011]迷宫探险 【记忆化搜索dp + 概率】

    题目 输入格式 输出格式 仅包含一个数字,表示在执行最优策略时,人物活着走出迷宫的概率.四舍五入保留3位小数. 输入样例 4 3 3 2 .$. A#B A#C @@@ 143 37 335 85 9 ...

  2. P2489 [SDOI2011]迷宫探险 概率dp

    LINK:迷宫探险 题目中要求在最优的策略下的最大概率 而并非期望概率. 一个坑点 题目中虽然没有明说 但是 探险者是知道地图的模样和每个陷阱的概率的. 所以才有最优策略一说. 最优策略尽管不知道可以 ...

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

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

  4. BZOJ 2246 [SDOI2011]迷宫探险 (记忆化搜索)

    题目大意:太长了,略 bzoj luogu 并没有想到三进制状压 题解: 3进制状压陷阱的状态,0表示这种陷阱的状态未知,1已知危险,2已知不危险 然后预处理出在当前状态下,每种陷阱有害的概率,设为$ ...

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

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

  6. [Bzoj2246]迷宫探险(概率+DP)

    Description 题目链接 Solution 用三进制表示陷阱状态,1表示有害,2表示无害,0表示不知道 用\(f[S][i]\)表示状态为S时陷阱i有害的概率,这个可以预处理出 \(d[S][ ...

  7. 2018年东北农业大学春季校赛 D wyh的迷宫【搜索】

    链接:https://www.nowcoder.com/acm/contest/93/D来源:牛客网 题目描述 给你一个n*m的迷宫,这个迷宫中有以下几个标识: s代表起点 t代表终点 x代表障碍物 ...

  8. 递归 dfs 记忆化搜索 动态规划

    今天做洛谷P1434 [SHOI2002]滑雪 的时候仔细想了想记忆化搜索 现在总结一下 为了描述问题的某一状态,必须用到该状态的上一状态,而描述上一状态,又必须用到上一状态的上一状态……这种用自已来 ...

  9. 洛谷P1605 迷宫 深度搜索 模板!

    题目背景 给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过.给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案.在迷宫中移动有上下左右四种方式,每次只能移 ...

随机推荐

  1. .net获取excel表的内容(OleDB方法)

    首先引用组件和命名空间 using Microsoft.Office.Interop.Excel; using System.Data.OleDb; 然后把excel上传到指定路径 上传文件方法省略 ...

  2. Scala学习(八)---Scala继承

    Scala继承 摘要: 在本篇中,你将了解到Scala的继承与Java和C++最显著的不同.要点包括: 1. extends.final关键字和Java中相同 2. 重写方法时必须用override ...

  3. Python高阶函数--map

    map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把list 的每个元素依次作用在函数 f 上,得到一个新的 list 并返回. 例如,对于lis ...

  4. [UWP 自定义控件]了解模板化控件(1):基础知识

    1.概述 UWP允许开发者通过两种方式创建自定义的控件:UserControl和TemplatedControl(模板化控件).这个主题主要讲述如何创建和理解模板化控件,目标是能理解模板化控件常见的知 ...

  5. Centos 6.9下部署Oracle 11G数据库环境的操作记录

    操作系统:Centos6.9(64Bit)Oracle:11g .11.2.0.4.0版本Ip地址:172.16.220.139 废话不多说了,下面记录安装过程:1)安装桌面环境 [root@vm01 ...

  6. Linux下monit进程管理操作梳理

    Monit对运维人员来说可谓神器,它是一款功能非常丰富的进程.文件.目录和设备的监测工具,用于Unix平台.它可以自动修复那些已经停止运作的程序,特使适合处理那些由于多种原因导致的软件错误.Monit ...

  7. 百度之星-day2-1004-二分答案

    由于序列有序,求其中一个最优解,二分答案即可,注意二分时上边界满足才保存 #include<iostream> #include<stdio.h> #include<st ...

  8. 小学四则运算APP 第二阶段冲刺

    第一阶段实现最基本的四则运算计算,最原始的所以还没有美化 xml文件     <LinearLayout xmlns:android="http://schemas.android.c ...

  9. 编写一个shell脚本来编译并运行java代码

    概述 编译和运行java分别要用到javac命令和java命令,虽然可以使用IDE(比如eclipse,InteliJ,NetBean...),按一下快捷键就可以实现编译并运行,但是,在之前还要配置一 ...

  10. Bash on Ubuntu on Windows 到底想干啥?apt update又能解决啥问题?