题目链接

求最大的存活概率,DP+记忆化。

用f[s][x][y][hp]表示在s状态,(x,y)点,血量为hp时的存活概率。

s是个三进制数,记录每个陷阱无害/有害/未知。

转移时比较容易,主要是在陷阱未知时需要知道当前状态这个陷阱为有害/无害的概率,并用这两个概率相加。

如何求某个状态下未知陷阱是否有害的概率呢(以下求有害概率,即 有害/(有害+无害))

DFS枚举每个陷阱已知有害/无害/未知的状态,我们需要处理未知陷阱在该状态下的概率。

枚举每个未知的陷阱,再枚举2^K的概率数组,只有当满足所有已知陷阱的状态时(未知的有/无解都加),才可以更新当前陷阱有害/无害的概率。

这个概率数组感觉比较迷啊。。是K个陷阱满足该状态时的概率。

注意: 再回到一个点(如起点)是可行的!不要随便剪。。

//15480kb	156ms
#include <cstdio>
#include <cctype>
#include <algorithm>
const int N=33,to[5]={1,0,-1,0,1}; int n,m,K,K_2,H,pi[N],sta[6];
double P[255][6],tmp[2],f[N][N][6][255];
bool vis[N][N][6][255];
char mp[N][N]; void DFS(int x)
{
if(x==K)
{
int now=0;
for(int i=K-1; ~i; --i) now=now*3+sta[i];
for(int p=0; p<K; ++p)
if(sta[p]==2)
{
tmp[0]=tmp[1]=0;//该陷阱有害/无害的概率
for(int i=0; i<K_2; ++i)
{
bool f=1;
for(int j=0; j<K; ++j)
if(sta[j]==2) ;
else if(((i>>j)&1)!=sta[j]) {f=0; break;}
if(f) tmp[(i>>p)&1]+=pi[i];//!
}
P[now][p]=tmp[1]/(tmp[0]+tmp[1]);
}
}
else
{
sta[x]=0, DFS(x+1);
sta[x]=1, DFS(x+1);
sta[x]=2, DFS(x+1);
}
}
inline int Change(int s,int p,int to)
{
int t=1; while(p--) t*=3;
return s-(2-to)*t;
}
#define Now f[x][y][hp][s]
double Solve(int x,int y,int hp,int s)
{
if(!hp) return 0;
if(mp[x][y]=='@') return 1.0;
if(vis[x][y][hp][s]) return f[x][y][hp][s];
vis[x][y][hp][s]=1;//状态比较多不好判重啊。。直接在这设vis=1.
for(int xn,yn,i=0; i<4; ++i)
{
xn=x+to[i], yn=y+to[i+1];
if(!xn||!yn||xn>n||yn>m||mp[xn][yn]=='#') continue;
char ch=mp[xn][yn];
if(ch=='.'||ch=='@'||ch=='$') Now=std::max(Now,Solve(xn,yn,hp,s));
else if(isalpha(ch)){
int ts=s,id=ch-'A';
for(int t=id; t; --t) ts/=3;
if(!(ts%3)) Now=std::max(Now,Solve(xn,yn,hp,s));
else if(ts%3==1) Now=std::max(Now,Solve(xn,yn,hp-1,s));
else Now=std::max(Now,Solve(xn,yn,hp-1,Change(s,id,1))*P[s][id]+Solve(xn,yn,hp,Change(s,id,0))*(1-P[s][id]));
}
}
return Now;
} int main()
{
scanf("%d%d%d%d",&n,&m,&K,&H);
int sx=0,sy;
for(int i=1; i<=n; ++i)
{
scanf("%s",mp[i]+1);
if(!sx){
for(int j=1; j<=m; ++j)
if(mp[i][j]=='$') sx=i,sy=j;
}
}
K_2=1<<K;
for(int i=0; i<K_2; ++i) scanf("%d",&pi[i]);
DFS(0);
int sta=1;
for(int i=K; i; --i) sta*=3;
// int sta=0;
// for(int i=K; i; --i) sta=sta*3+2;
printf("%.3lf",Solve(sx,sy,H,sta-1)); return 0;
}

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

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

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

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

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

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

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

  4. 【BZOJ】1415 [Noi2005]聪聪和可可 期望DP+记忆化搜索

    [题意]给定无向图,聪聪和可可各自位于一点,可可每单位时间随机向周围走一步或停留,聪聪每单位时间追两步(先走),问追到可可的期望时间.n<=1000. [算法]期望DP+记忆化搜索 [题解]首先 ...

  5. 【bzoj5123】[Lydsy12月赛]线段树的匹配 树形dp+记忆化搜索

    题目描述 求一棵 $[1,n]$ 的线段树的最大匹配数目与方案数. $n\le 10^{18}$ 题解 树形dp+记忆化搜索 设 $f[l][r]$ 表示根节点为 $[l,r]$ 的线段树,匹配选择根 ...

  6. [题解](树形dp/记忆化搜索)luogu_P1040_加分二叉树

    树形dp/记忆化搜索 首先可以看出树形dp,因为第一个问题并不需要知道子树的样子, 然而第二个输出前序遍历,必须知道每个子树的根节点,需要在树形dp过程中记录,递归输出 那么如何求最大加分树——根据中 ...

  7. poj1664 dp记忆化搜索

    http://poj.org/problem?id=1664 Description 把M个相同的苹果放在N个相同的盘子里,同意有的盘子空着不放,问共同拥有多少种不同的分法?(用K表示)5.1.1和1 ...

  8. 状压DP+记忆化搜索 UVA 1252 Twenty Questions

    题目传送门 /* 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 若 ...

  9. ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索

    ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...

随机推荐

  1. DNA序列编码中Hairpin的定义和计算

    DNA序列编码中Hairpin的定义和计算 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 [1] 张凯. DNA计算核酸编码优化及算法设计[D]. 2008. [2] Shin, ...

  2. python---基础知识回顾(一)(引用计数,深浅拷贝,列表推导式,lambda表达式,命名空间,函数参数逆收集,内置函数,hasattr...)

    一:列表和元组(引用计数了解,深浅拷贝了解) 序列:序列是一种数据结构,对其中的元素按顺序进行了编号(从0开始).典型的序列包括了列表,字符串,和元组 列表是可变的(可以进行修改),而元组和字符串是不 ...

  3. axios 参数拼接

    // 加载列表 getData () { this.$http .get("platform-framework/stucgbb/selectCHBBInit?type="+thi ...

  4. vue element-ui 实现点击查看审核记录

    <el-dialog title="审核信息" :visible.sync="seeVisible" width="30%" :bef ...

  5. bzoj千题计划291:bzoj3640: JC的小苹果

    http://www.lydsy.com/JudgeOnline/problem.php?id=3640 dp[i][j] 表示i滴血到达j的概率 dp[i][j] = Σ dp[i+val[i]][ ...

  6. bzoj千题计划247:bzoj4903: [Ctsc2017]吉夫特

    http://uoj.ac/problem/300 预备知识: C(n,m)是奇数的充要条件是 n&m==m 由卢卡斯定理可以推出 选出的任意相邻两个数a,b 的组合数计算C(a,b)必须是奇 ...

  7. bzoj千题计划196:bzoj4826: [Hnoi2017]影魔

    http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...

  8. python学习笔记7-网络编程

    import urllib.request import json,requests #urlib模块,不常用 url = 'http://api.nnzhp.cn/api/user/stu_info ...

  9. Python 入门基础9 --函数基础2 实参与形参

    今日内容: 一.函数参数 1.形参与实参定义 2.实参分类 3.形参分类 4.可变参数的整体使用 一.形参与实参定义 def fn(参数们): pass 1.1 形参 定义函数,在括号内声明的变量名, ...

  10. Comparable和Comparator的区别&Collections.sort的两种用法

    在Java集合的学习中,我们明白了: 看到tree,可以按顺序进行排列,就要想到两个接口.Comparable(集合中元素实现这个接口,元素自身具备可比性),Comparator(比较器,传入容器构造 ...