BZOJ2246 [SDOI2011]迷宫探险 【记忆化搜索dp + 概率】
题目
输入格式
输出格式
仅包含一个数字,表示在执行最优策略时,人物活着走出迷宫的概率。四舍五入保留3位小数。
输入样例
4 3 3 2
.$.
A#B
A#C
@@@
143 37 335 85 95 25 223 57
输出样例
0.858
提示
题解
毒瘤dp题
我们设\(f[x][y][s][h]\)表示从点\((x,y)\)出发,所有陷阱状态为\(s\),生命值为\(h\),存活的期望概率
我们枚举邻点,选择存活概率最大的作为当前\(f\)的值
除了墙,有以下情况:
①如果是空地或者终点,直接转移\(f[nx][ny][s][h]\)
②如果是陷阱:
1、如果陷阱已知
无害则同空地的转移
有害则转移的同时\(h - 1\)
2、如果陷阱位置
那么就是\(g[s][t] * f[nx][ny][s'][h - 1] + (1 - g[s][t]) * f[nx][ny][s''][h]\)
其中\(g[s][t]\)表示在已知状态为s的情况下,陷阱\(t\)有害的概率,可以预处理出来
\(s'\)和\(s''\)就是加入新状态的s
至于g数组的预处理,对于每种s,枚举未知位置的子集,将各种情况有害的加到对应陷阱去,然后除以总值
为什么换一个搜索顺序才能A???
#include<iostream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define REP(i,n) for (int i = 1; i <= (n); i++)
using namespace std;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
double f[32][32][250][6],g[250][6],p[100];
int vis[32][32][250][6],bin[10];
int n,m,K,H,Sx,Sy,X[4] = {1,0,-1,0},Y[4] = {0,-1,0,1};
int G[32][32];
void init(){
n = read(); m = read(); K = read(); H = read();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++){
char c = getchar();
while (!isprint(c)) c = getchar();
if (c == '.') G[i][j] = 0;
else if (c == '#') G[i][j] = -1;
else if (c == '$') G[i][j] = 0,Sx = i,Sy = j;
else if (c == '@') G[i][j] = -2;
else G[i][j] = c - 'A' + 1;
}
//REP(i,n) {REP(j,m) printf("%d ",G[i][j]); puts("");}
bin[0] = 1;
for (int i = 1; i <= K; i++) bin[i] = bin[i - 1] * 3;
//REP(i,K) printf("%d ",bin[i]); puts("");
int maxv = (1 << K) - 1,maxp = bin[K] - 1;
for (int s = 0; s <= maxv; s++) p[s] = read();
for (int s = 0; s <= maxp; s++){
int e = 0,t = 0; double sum = 0;
for (int i = s,j = 1; j <= K; j++,i /= 3){
if (i % 3 == 0) t |= (1 << j - 1);
else if (i % 3 == 2) e |= (1 << j - 1);
}
for (int i = t; ; i = (i - 1) & t){
int to = (e | i);
sum += p[to];
for (int j = 1; j <= K; j++)
if (to & (1 << j - 1)) g[s][j] += p[to];
if (!i) break;
}
for (int i = 1; i <= K; i++)
g[s][i] /= sum;
}
}
double F(int x,int y,int s,int h){
if (vis[x][y][s][h]) return f[x][y][s][h];
if (h == 0){
vis[x][y][s][h] = 1;
return f[x][y][s][h] = 0;
}
if (G[x][y] == -2){
vis[x][y][s][h] = 1;
return f[x][y][s][h] = 1;
}
vis[x][y][s][h] = 1;
double& ff = f[x][y][s][h];
ff = 0;
int nx,ny;
for (int k = 0; k < 4; k++){
nx = x + X[k];
ny = y + Y[k];
if (nx < 1 || ny < 1 || nx > n || ny > m || G[nx][ny] == -1) continue;
if (G[nx][ny] == 0 || G[nx][ny] == -2){
ff = max(ff,F(nx,ny,s,h));
}
else {
int t = G[nx][ny];
if ((s / bin[t - 1]) % 3 == 1) ff = max(ff,F(nx,ny,s,h));
else if ((s / bin[t - 1]) % 3 == 2) ff = max(ff,F(nx,ny,s,h - 1));
else {
ff = max(ff,g[s][t] * F(nx,ny,s + 2 * bin[t - 1],h - 1) + (1 - g[s][t]) * F(nx,ny,s + bin[t - 1],h));
}
}
}
return ff;
}
int main(){
init();
if (n == 0) return 0;
else printf("%.3lf\n",F(Sx,Sy,0,H));
return 0;
}
BZOJ2246 [SDOI2011]迷宫探险 【记忆化搜索dp + 概率】的更多相关文章
- BZOJ 2246 [SDOI2011]迷宫探险 (记忆化搜索)
题目大意:太长了,略 bzoj luogu 并没有想到三进制状压 题解: 3进制状压陷阱的状态,0表示这种陷阱的状态未知,1已知危险,2已知不危险 然后预处理出在当前状态下,每种陷阱有害的概率,设为$ ...
- 记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence
题目传送门 /* 记忆化搜索(DP+DFS):dp[i][j] 表示第i到第j个字符,最少要加多少个括号 dp[x][x] = 1 一定要加一个括号:dp[x][y] = 0, x > y; 当 ...
- HDU 1078 FatMouse and Cheese 记忆化搜索DP
直接爆搜肯定超时,除非你加了某种凡人不能想出来的剪枝...555 因为老鼠的路径上的点满足是递增的,所以满足一定的拓补关系,可以利用动态规划求解 但是复杂的拓补关系无法简单的用循环实现,所以直接采取记 ...
- 记忆化搜索 dp学习~2
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1331 Function Run Fun Time Limit: 2000/1000 MS (Java/ ...
- 【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】
Solution 注意取模!!! Code #include<bits/stdc++.h> #define mod 1000000007 #define LL long long usin ...
- hdu1331&&hdu1579记忆化搜索(DP+DFS)
这两题是一模一样的``` 题意:给了一系列递推关系,但是由于这些递推很复杂,所以递推起来要花费很长的时间,所以我要编程序在有限的时间内输出答案. w(a, b, c): 如果a,b,c中有一个值小于等 ...
- HDU - 6415 多校9 Rikka with Nash Equilibrium(纳什均衡+记忆化搜索/dp)
Rikka with Nash Equilibrium Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K ...
- hdu 4960 记忆化搜索 DP
Another OCD Patient Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Ot ...
- HNU OJ10086 挤挤更健康 记忆化搜索DP
挤挤更健康 Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit users: 339, A ...
随机推荐
- [Tomcat]如何清理缓存
步骤: 1.进入tomcat文件夹 2.找到work目录 3.work目录下有个catalina目录 4.将catalina目录整个删除
- java 序列化Serializable 详解
Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是 ...
- OpenGL Frustum参数设置
opengl中使用Frustum来设置透视投影,函数原型: frustum(float left, float right, float buttom, float top, float near, ...
- Unity3d中MonoBehavior默认函数的执行顺序和生命周期
Awake()在MonoBehavior创建后就立刻调用,在脚本实例的整个生命周期中,Awake函数仅执行一次:如果游戏对象(即gameObject)的初始状态为关闭状态,那么运行程序,Awake函数 ...
- 五、Pandas玩转数据
Series的简单运算 import numpy as np import pandas as pd s1=pd.Series([1,2,3],index=['A','B','C']) print(s ...
- ios UITableViewCell重用问题
在写sina 微博界面的过程中使用到了cell,那么就是在cell上添加一些控件,但是由于每条微博的内容都是不同的,所以在显示的过程中,出现了内容重叠的问题,其实就是UITableViewCell重用 ...
- PAT 乙级 1009
题目 题目地址:PAT 乙级 1009 题解 本题本身属于比较简单的字符串操作题,但是因为对于string的操作和函数不熟悉导致本题做起来很费劲,需要加强对于string类以及相关方法的理解和熟练程度 ...
- 简单的Redis数据迁移
dump迁移 1.安装redis-dump工具 sudo apt-get install ruby rubygems ruby-devel -y gem sources --add http://ge ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
- Django 千锋培训的学习笔记(1)
Django 千锋培训读书笔记 https://www.bilibili.com/video/av17879644/?p=1 切换到创建项目的目录 cd C:\Users\admin\Desktop\ ...