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 ...
随机推荐
- CSS3 transform详解,关于如何使用transform
transform是css3的新特性之一.有了它可以box module变的更真实,这篇文章将全面介绍关于transform的使用. transform的作用 transform可以让元素应用 2D ...
- Activity启动流程分析
我们来看一下 startActivity 过程的具体流程.在手机桌面应用中点击某一个 icon 之后,实际上最终就是通过 startActivity 去打开某一个 Activity 页面.我们知道 A ...
- TLS回调函数以及反调试简单使用
TLS回调函数以及反调试简单使用 0x00 TLS介绍 TLS(Thread Local Storage,线程局部储存),主要用于给线程独立的传值,由于线程不拥有进程的资源,所以几个同一进程的几个线 ...
- Sql Or NoSql,看完这一篇你就懂了(转五月的仓颉)
前言 你是否在为系统的数据库来一波大流量就几乎打满CPU,日常CPU居高不下烦恼?你是否在各种NoSql间纠结不定,到底该选用那种最好?今天的你就是昨天的我,这也是写这篇文章的初衷. 这篇文章是我好几 ...
- JavaScript动画实例:动感小球
已知圆的坐标方程为: X=R*SIN(θ) Y=R*COS(θ) (0≤θ≤2π) 将0~2π区间等分48段,即设定间隔dig的值为π/24.θ初始值从0开始,按曲线方程求得坐标值(x,y), ...
- bzoj3892[Usaco2014 Dec]Marathon*
bzoj3892[Usaco2014 Dec]Marathon 题意: 在二维平面上有N个点,从(x1,y1)到(x2,y2)的代价为|x1-x2|+|y1-y2|.求从1号点出发,按从1到N的顺序依 ...
- combogrid设置多选,并获取多选的值
1.combogrid设置多选 1.添加该属性 multiple: true, 2.添加该列 {field:'ck',checkbox:true}, 2.获取多选的值 var arr = $(&quo ...
- 使用Python进行自动化测试
目前大家对Python都有一个共识,就是他对测试非常有用,自动化测试里Python用途也很广,但是Python到底怎么进行自动化测试呢?今天就简单的向大家介绍一下怎么使用Python进行自动化测试,本 ...
- 使用nvm安装node,运行node报错 node: command not found
1. 使用nvm安装node之后,直接运行node命令会报错 node: command not found 需要使用nvm ls 查询一下当前使用的安装的node版本,然后使用node use 版 ...
- GPO - Folder Mapping via GPO
Create a Group Policy on AD DC Server. The GPO policy will come into effect on the next login, or us ...