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 ...
随机推荐
- Linux下的I/O复用
读书笔记 I/O复用使得程序能同时监听多个文件描述符,这对提高程序的性能至关重要. Linux下实现I/O复用的系统调用主要有select, poll, epoll. select: 用户通过3个参数 ...
- POJ 3133 Manhattan Wiring (插头DP,轮廓线,经典)
题意:给一个n*m的矩阵,每个格子中有1个数,可能是0或2或3,出现2的格子数为2个,出现3的格子数为2个,要求将两个2相连,两个3相连,求不交叉的最短路(起终点只算0.5长,其他算1). 思路: 这 ...
- iOS打包上传app store各种问题解决总结
问题1 this action could not be completed. try again 问题2 there was an error sending data to the iTunes ...
- UVA 12549 Sentry Robots (最小点覆盖)
这道题挺像hdu 5093 Battle ships的,不过那道题是要求最多放置的点数,而这道题是要求最小点覆盖. 顶点覆盖的定义是:在G中任意边至少有一个端点属于顶点集合S. 一个重要的位置有(x, ...
- MINST手写数字识别(三)—— 使用antirectifier替换ReLU激活函数
这是一个来自官网的示例:https://github.com/keras-team/keras/blob/master/examples/antirectifier.py 与之前的MINST手写数字识 ...
- Sublime 设置移动光标快捷键
发现问题 在使用Sublime和其他编辑器一个很不爽的问题是:在输入一个函数或者有左右的符号或者在引号内时,总是要跳出来,无奈方向键又在主键盘的另一边,只能不断的切换,太特么操蛋,就不能让手指不离开主 ...
- jQuery和CSS的拍摄效果
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- js的正则表达式总结
1.8-20位数字 or 字母 or 特殊字符 var reg = /^[0-9a-zA-Z!@#$%^&*()_+-/.]{8,20}$/; 2.8-20位 数字+字母+特殊字符 //正则 ...
- Java代码实现文件上传(转载)
刚刚发表了一篇Java发送电子邮件,以前真是没注意,commons里这么多常用项目,惭愧呀,直到现在回顾;要学习的真是太多了,还是缺少真正的学习能力... 这里用到的是commons-fileuplo ...
- ios之NSURLRequest&NSURLConnection
网络编程中一般都是经过 请求--->连接--->响应 (request --> connection --> response)这个过程. 一般的步骤是这样的: ...