P2489 [SDOI2011]迷宫探险 概率dp
LINK:迷宫探险
题目中要求在最优的策略下的最大概率 而并非期望概率。
一个坑点 题目中虽然没有明说 但是 探险者是知道地图的模样和每个陷阱的概率的。
所以才有最优策略一说。
最优策略尽管不知道可以随便走取max即可。
容易想到 对于当前状态 有 x,y,hp,s 来描述 。倒着设状态 那就是当前状态能到达终点的最大概率。
定义hp s都是递增的 不过还是不能线性递推。存在问题 可能状态之间可以互相转移的问题。
显然状态转移回来是不必要的 所以此时概率为0 利用dfs栈可以很容易判断出来 所以考虑记忆化搜索。
不过这引出了另外一个问题 当前状态可能被多次访问到 不过当前状态被第一次访问到已经被标记了 此时可能不是最优的。
容易想到转移到当前状态最多只有4种可能都记录下来即可。
6.16 Update:被wn给hack掉了 发现上面的思路在能走回路的时候会挂掉。
原因:存在一种最优方案使得从某个点走到另外一个点然后再跑回来的情况。
同时也存在一开始就跑过去的情况是最优的。
实际上上述做法能解决第一种情况 而第二种情况就在第一种情况被解决时 被卡掉了。
因为 可以走完这步 发现无毒 然后一些较优的状态可能被一些情况给卡掉了 因为原地乱转的原因。
一个好的解决方法:强制不让其乱转 保证状态之间的拓扑关系 这样就不会出现问题了。
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-8
#define sq sqrt
#define mod 998244353
#define S second
#define F first
#define Set(a,v) memset(a,v,sizeof(a))
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
//偷税吧 少年
const int MAXN=33,N=244;
int n,m,H,k,maxx,s1,s2,maxx1,ans;
int w[1<<5],b[N],id;
int vis[MAXN][MAXN][6][N];
db g[N][6],f[MAXN][MAXN][6][N];
char a[MAXN][MAXN];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
vector<pii>v[MAXN][MAXN][MAXN];
int mark[MAXN][MAXN],cc[N];
inline int pd(int s,int x)
{
return s>>x-1&1;
}
inline void dfs(int x,int y,int s,int xx,int yy)
{
if(mark[x][y]==id)return;
mark[x][y]=id;
if(a[x][y]=='@'||(a[x][y]>='A'&&a[x][y]<='Z'&&!pd(s,a[x][y]-'A'+1)&&(x!=xx||y!=yy)))
{
v[s][xx][yy].pb(mk(x,y));return;
}
for(int i=0;i<4;++i)
{
int wx=dx[i]+x;
int wy=dy[i]+y;
if(wx<=0||wx>n||wy<=0||wy>m)continue;
if(a[wx][wy]=='#')continue;
dfs(wx,wy,s,xx,yy);
}
}
inline void prepare()
{
rep(1,n,i)rep(1,m,j)
{
if(a[i][j]=='#'||a[i][j]=='@')continue;
rep(0,maxx,s)
{
++id;
dfs(i,j,s,i,j);
}
}
}
inline db dp(int x,int y,int hp,int s)
{
if(vis[x][y][hp][s])return f[x][y][hp][s];
vis[x][y][hp][s]=1;
if(hp==0)return f[x][y][hp][s]=0;
if(a[x][y]=='@')return f[x][y][hp][s]=1;
db ans=0;int ww=cc[s];
vep(0,v[ww][x][y].size(),i)
{
int xx=v[ww][x][y][i].F;
int yy=v[ww][x][y][i].S;
if(a[xx][yy]=='@')ans=max(ans,dp(xx,yy,hp,s));
else
{
int ss=a[xx][yy]-'A'+1;
if(s/b[ss-1]%3==1)ans=max(ans,dp(xx,yy,hp-1,s));
if(s/b[ss-1]%3==0)
ans=max(ans,dp(xx,yy,hp-1,s+b[ss-1])*g[s][ss]
+dp(xx,yy,hp,s+b[ss-1]*2)*(1-g[s][ss]));
}
}
return f[x][y][hp][s]=ans;
}
int main()
{
//freopen("1.in","r",stdin);
gt(n);gt(m);gt(k);gt(H);
rep(1,n,i)
{
gc(a[i]);
rep(1,m,j)if(a[i][j]=='$')s1=i,s2=j;
}
maxx=1<<k;--maxx;b[0]=1;
rep(0,maxx,i)get(w[i]),ans+=w[i];
rep(1,k,i)b[i]=b[i-1]*3;
maxx1=b[k]-1;
rep(0,maxx1,i)
{
//0表示未知 1表示有毒 2表示无害.
int num=0;
rep(0,maxx,w1)//0表示无害 1表示有毒
{
int flag=0;
rep(1,k,w2)
{
if(i/b[w2-1]%3==0)continue;
if(i/b[w2-1]%3==1&&(w1>>w2-1&1))continue;
if(i/b[w2-1]%3==2&&!(w1>>w2-1&1))continue;
flag=1;
}
if(flag)continue;
num+=w[w1];
rep(1,k,j)
{
if(i/b[j-1]%3==1&&(w1>>j-1&1))continue;
if(i/b[j-1]%3==2&&!(w1>>j-1&1))continue;
if(i/b[j-1]%3==0)if(w1>>j-1&1)g[i][j]+=w[w1];
}
}
rep(1,k,j)
{
if(i/b[j-1]%3==1)g[i][j]=1;
if(i/b[j-1]%3==2)g[i][j]=0,cc[i]|=(1<<j-1);
if(i/b[j-1]%3==0)g[i][j]/=num;
}
}
prepare();
printf("%.3lf",dp(s1,s2,H,0));
return 0;
}
P2489 [SDOI2011]迷宫探险 概率dp的更多相关文章
- 【BZOJ2246】[SDOI2011]迷宫探险(搜索,动态规划)
[BZOJ2246][SDOI2011]迷宫探险(搜索,动态规划) 题面 BZOJ 洛谷 题解 乍一看似乎是可以求出每个东西是陷阱的概率,然而会发现前面走过的陷阱是不是陷阱实际上是会对当前状态产生影响 ...
- BZOJ2246 [SDOI2011]迷宫探险 【记忆化搜索dp + 概率】
题目 输入格式 输出格式 仅包含一个数字,表示在执行最优策略时,人物活着走出迷宫的概率.四舍五入保留3位小数. 输入样例 4 3 3 2 .$. A#B A#C @@@ 143 37 335 85 9 ...
- 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是个三进制数,记录每个陷阱无害/有害/未知. 转移时比较容易,主要是在 ...
- BZOJ2707 [SDOI2012]走迷宫 【概率dp + tarjan + 高斯消元】
题目 Morenan被困在了一个迷宫里.迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T.可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿着一条从该点出发的 ...
- BZOJ 2246 [SDOI2011]迷宫探险 (记忆化搜索)
题目大意:太长了,略 bzoj luogu 并没有想到三进制状压 题解: 3进制状压陷阱的状态,0表示这种陷阱的状态未知,1已知危险,2已知不危险 然后预处理出在当前状态下,每种陷阱有害的概率,设为$ ...
- 【Luogu】P2489迷宫探险(概率DP)
题目链接 设f[i][j][k][l]是当前在(i,j),对陷阱的了解状态为k(0表示了解该陷阱为无危险,1表示了解该陷阱有危险,2不了解),l表示当前血,走出迷宫的概率 dfsDP即可. 注意随时更 ...
- hdu 4035 2011成都赛区网络赛E 概率dp ****
太吊了,反正我不会 /* HDU 4035 dp求期望的题. 题意: 有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树, 从结点1出发,开始走,在每个结点i都有3种可能: 1.被杀死,回到结点 ...
- [转]概率DP总结 by kuangbin
概率类题目一直比较弱,准备把kuangbin大师傅总结的这篇题刷一下! 我把下面的代码换成了自己的代码! 原文地址:http://www.cnblogs.com/kuangbin/archive/20 ...
随机推荐
- 51nod1524 最大子段和V2
题干 N个整数组成的序列a[1],a[2],a[3],-,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数 ...
- 小师妹学JVM之:cache line对代码性能的影响
目录 简介 一个奇怪的现象 两个问题的答案 CPU cache line inc 和 add 总结 简介 读万卷书不如行万里路,讲了这么多assembly和JVM的原理与优化,今天我们来点不一样的实战 ...
- Jenkins 自动化(CI/DI)部署
1. 背景介绍 在实际开发中,经常要一边开发一边测试,经常为了一个功能而不断更新版本,这些情况都会涉及到频繁的打包.部署:手动打包的涉及到项目上传.打包.发布等很多重复工作: 那么,有一种工具能够实现 ...
- 图形处理:给 Canvas 文本填充线性渐变
作者:凹凸曼 - Barrior 在 Canvas 中对文本填充水平或垂直的线性渐变可以轻易实现,而带角度的渐变就复杂很多:就好像下面这样,假设文本矩形宽为 W, 高为 H, 左上角坐标为 X, Y. ...
- android手机的微信H5弹出的软键盘挡住了文本框,如何解决?
window.addEventListener("resize", function () { if (document.activeElement.tagName == &quo ...
- 卸载wsl子系统
1>在powershell中输入下面的代码 wslconfig /l #显示出你安装的列表. wslconfig /u debian #debian为上述列表中的名字 注销子系统 2>打开 ...
- python 三维散点插值 griddata
#三维点插值#在三维空间中,利用实际点的值推算出网格点的值import numpy as np point_grid =np.array([[0.0,0.0,0.0],[0.4,0.4,0.4],[0 ...
- 数据可视化基础专题(十五):pyecharts 基础(二)flask 框架整合
Flask 前后端分离 Step 1: 新建一个 Flask 项目 $ mkdir pyecharts-flask-demo $ cd pyecharts-flask-demo $ mkdir tem ...
- web 部署专题(二):gunicore 并发部署(用gunicorn+gevent启动Flask项目)
转自:https://blog.csdn.net/dutsoft/article/details/51452598 Flask,webpy,Django都带着 WSGI server,当然性能都不好, ...
- 数据可视化之 图表篇(五) PowerBI图表不够炫酷?来看看这个
现在这个大数据时代,每时每刻.各行各业都在产生多种多样的海量数据,如何简单高效的来理解.挖掘这些数据,发现背后的见解就非常重要. 本文介绍这个图表就可以帮你快速发现海量数据背后的见解,微软研究院打造的 ...