题目







输入格式

输出格式

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

  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. 面试题--JAVA中静态块、静态变量加载顺序

    最后给大家一道面试题练练手,要求写出其结果(笔试) public class StaticTest { public static int k = 0; public static StaticTes ...

  2. Win10系统64位快速专业安装版 V2016年

    win10系统64位快速专业安装版 V2016年2月 系统下载:http://www.xitongma.com/ Ghost Win10 64位正式装机专业版2016 微软向Windows用户推送了w ...

  3. POJ 1741 Tree (树的分治,树的重心)

    题意:给一棵树,n个节点,给定一个数k,求任意满足dist(a,b)<=k的点对的数量. 思路: 这道题的思路比较简单,但是细节很多. 此题可以用分治法,如何分治? (1)如果path(a,b) ...

  4. POJ Washing Clothes 洗衣服 (01背包,微变型)

    题意:有多种颜色的衣服,由两个人合作来洗,必须洗完一种颜色才能洗下一种,求需要多少时间能洗完. 思路:将衣服按颜色分类,对每种颜色进行01背包,容量上限是该种颜色衣服全部洗完的耗时长一半,其实就是在最 ...

  5. Android串口通信

    前段时间因为工作需要研究了一下android的串口通信,网上有很多讲串口通信的文章,我在做的时候也参考了很多文章,现在就将我学习过程中的一些心得分享给大家,希望可以帮助大家在学习的时候少走一些弯路,有 ...

  6. 校内选拔I题题解 构造题 Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 2) ——D

    http://codeforces.com/contest/574/problem/D Bear and Blocks time limit per test 1 second memory limi ...

  7. WPF中实现两个窗口之间传值

    在使用WPF的时候,我们经常会用到窗体之间传值,下面示例主窗口传值到子窗口,子窗口传值到主窗口的方法. 一.主窗口向子窗口传值 主窗口向子窗口传值主要方法就是在子窗口建立一个接收主窗口值的变量,然后实 ...

  8. 关于img

    为img添加属性max-width min-height之类的属性可以对图片溢出部分实行自动裁剪功能 非常方便!!!!!!!!!(仅适用于那些原始图片大于max-width,max-height的图片 ...

  9. var、let、const声明变量的区别

    let和var声明变量的区别:1.let所声明的变量只在let命令所在的代码块内有效.(块级作用域) for(let i=0;i<10;i++){ // ... } console.log(i) ...

  10. jsTree展开根节点 设置用户图标

    $("#jstree").on("loaded.jstree", function (event, data) { var n = 0; var root = ...