题目







输入格式

输出格式

仅包含一个数字,表示在执行最优策略时,人物活着走出迷宫的概率。四舍五入保留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???

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cctype>
  4. #include<cstring>
  5. #include<algorithm>
  6. #define REP(i,n) for (int i = 1; i <= (n); i++)
  7. using namespace std;
  8. inline int read(){
  9. int out = 0,flag = 1; char c = getchar();
  10. while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
  11. while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
  12. return out * flag;
  13. }
  14. double f[32][32][250][6],g[250][6],p[100];
  15. int vis[32][32][250][6],bin[10];
  16. int n,m,K,H,Sx,Sy,X[4] = {1,0,-1,0},Y[4] = {0,-1,0,1};
  17. int G[32][32];
  18. void init(){
  19. n = read(); m = read(); K = read(); H = read();
  20. for (int i = 1; i <= n; i++)
  21. for (int j = 1; j <= m; j++){
  22. char c = getchar();
  23. while (!isprint(c)) c = getchar();
  24. if (c == '.') G[i][j] = 0;
  25. else if (c == '#') G[i][j] = -1;
  26. else if (c == '$') G[i][j] = 0,Sx = i,Sy = j;
  27. else if (c == '@') G[i][j] = -2;
  28. else G[i][j] = c - 'A' + 1;
  29. }
  30. //REP(i,n) {REP(j,m) printf("%d ",G[i][j]); puts("");}
  31. bin[0] = 1;
  32. for (int i = 1; i <= K; i++) bin[i] = bin[i - 1] * 3;
  33. //REP(i,K) printf("%d ",bin[i]); puts("");
  34. int maxv = (1 << K) - 1,maxp = bin[K] - 1;
  35. for (int s = 0; s <= maxv; s++) p[s] = read();
  36. for (int s = 0; s <= maxp; s++){
  37. int e = 0,t = 0; double sum = 0;
  38. for (int i = s,j = 1; j <= K; j++,i /= 3){
  39. if (i % 3 == 0) t |= (1 << j - 1);
  40. else if (i % 3 == 2) e |= (1 << j - 1);
  41. }
  42. for (int i = t; ; i = (i - 1) & t){
  43. int to = (e | i);
  44. sum += p[to];
  45. for (int j = 1; j <= K; j++)
  46. if (to & (1 << j - 1)) g[s][j] += p[to];
  47. if (!i) break;
  48. }
  49. for (int i = 1; i <= K; i++)
  50. g[s][i] /= sum;
  51. }
  52. }
  53. double F(int x,int y,int s,int h){
  54. if (vis[x][y][s][h]) return f[x][y][s][h];
  55. if (h == 0){
  56. vis[x][y][s][h] = 1;
  57. return f[x][y][s][h] = 0;
  58. }
  59. if (G[x][y] == -2){
  60. vis[x][y][s][h] = 1;
  61. return f[x][y][s][h] = 1;
  62. }
  63. vis[x][y][s][h] = 1;
  64. double& ff = f[x][y][s][h];
  65. ff = 0;
  66. int nx,ny;
  67. for (int k = 0; k < 4; k++){
  68. nx = x + X[k];
  69. ny = y + Y[k];
  70. if (nx < 1 || ny < 1 || nx > n || ny > m || G[nx][ny] == -1) continue;
  71. if (G[nx][ny] == 0 || G[nx][ny] == -2){
  72. ff = max(ff,F(nx,ny,s,h));
  73. }
  74. else {
  75. int t = G[nx][ny];
  76. if ((s / bin[t - 1]) % 3 == 1) ff = max(ff,F(nx,ny,s,h));
  77. else if ((s / bin[t - 1]) % 3 == 2) ff = max(ff,F(nx,ny,s,h - 1));
  78. else {
  79. 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));
  80. }
  81. }
  82. }
  83. return ff;
  84. }
  85. int main(){
  86. init();
  87. if (n == 0) return 0;
  88. else printf("%.3lf\n",F(Sx,Sy,0,H));
  89. return 0;
  90. }

BZOJ2246 [SDOI2011]迷宫探险 【记忆化搜索dp + 概率】的更多相关文章

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

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

  2. 记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence

    题目传送门 /* 记忆化搜索(DP+DFS):dp[i][j] 表示第i到第j个字符,最少要加多少个括号 dp[x][x] = 1 一定要加一个括号:dp[x][y] = 0, x > y; 当 ...

  3. HDU 1078 FatMouse and Cheese 记忆化搜索DP

    直接爆搜肯定超时,除非你加了某种凡人不能想出来的剪枝...555 因为老鼠的路径上的点满足是递增的,所以满足一定的拓补关系,可以利用动态规划求解 但是复杂的拓补关系无法简单的用循环实现,所以直接采取记 ...

  4. 记忆化搜索 dp学习~2

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1331 Function Run Fun Time Limit: 2000/1000 MS (Java/ ...

  5. 【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

    Solution 注意取模!!! Code #include<bits/stdc++.h> #define mod 1000000007 #define LL long long usin ...

  6. hdu1331&&hdu1579记忆化搜索(DP+DFS)

    这两题是一模一样的``` 题意:给了一系列递推关系,但是由于这些递推很复杂,所以递推起来要花费很长的时间,所以我要编程序在有限的时间内输出答案. w(a, b, c): 如果a,b,c中有一个值小于等 ...

  7. HDU - 6415 多校9 Rikka with Nash Equilibrium(纳什均衡+记忆化搜索/dp)

    Rikka with Nash Equilibrium Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K ...

  8. hdu 4960 记忆化搜索 DP

    Another OCD Patient Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Ot ...

  9. HNU OJ10086 挤挤更健康 记忆化搜索DP

    挤挤更健康 Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit users: 339, A ...

随机推荐

  1. Linux下的I/O复用

    读书笔记 I/O复用使得程序能同时监听多个文件描述符,这对提高程序的性能至关重要. Linux下实现I/O复用的系统调用主要有select, poll, epoll. select: 用户通过3个参数 ...

  2. POJ 3133 Manhattan Wiring (插头DP,轮廓线,经典)

    题意:给一个n*m的矩阵,每个格子中有1个数,可能是0或2或3,出现2的格子数为2个,出现3的格子数为2个,要求将两个2相连,两个3相连,求不交叉的最短路(起终点只算0.5长,其他算1). 思路: 这 ...

  3. iOS打包上传app store各种问题解决总结

    问题1 this action could not be completed. try again 问题2 there was an error sending data to the iTunes ...

  4. UVA 12549 Sentry Robots (最小点覆盖)

    这道题挺像hdu 5093 Battle ships的,不过那道题是要求最多放置的点数,而这道题是要求最小点覆盖. 顶点覆盖的定义是:在G中任意边至少有一个端点属于顶点集合S. 一个重要的位置有(x, ...

  5. MINST手写数字识别(三)—— 使用antirectifier替换ReLU激活函数

    这是一个来自官网的示例:https://github.com/keras-team/keras/blob/master/examples/antirectifier.py 与之前的MINST手写数字识 ...

  6. Sublime 设置移动光标快捷键

    发现问题 在使用Sublime和其他编辑器一个很不爽的问题是:在输入一个函数或者有左右的符号或者在引号内时,总是要跳出来,无奈方向键又在主键盘的另一边,只能不断的切换,太特么操蛋,就不能让手指不离开主 ...

  7. jQuery和CSS的拍摄效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. js的正则表达式总结

    1.8-20位数字 or  字母 or 特殊字符 var reg = /^[0-9a-zA-Z!@#$%^&*()_+-/.]{8,20}$/; 2.8-20位 数字+字母+特殊字符 //正则 ...

  9. Java代码实现文件上传(转载)

    刚刚发表了一篇Java发送电子邮件,以前真是没注意,commons里这么多常用项目,惭愧呀,直到现在回顾;要学习的真是太多了,还是缺少真正的学习能力... 这里用到的是commons-fileuplo ...

  10. ios之NSURLRequest&NSURLConnection

    网络编程中一般都是经过  请求--->连接--->响应   (request  -->  connection  -->  response)这个过程. 一般的步骤是这样的: ...