题目







输入格式

输出格式

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

    文件:src/comps/uvm_driver.svh类: uvm_driver uvm_driver继承(C++中叫继承)自uvm_component,其中定义了两个Ports:seq_item_p ...

  2. shell中使用ssh

    ssh服务是不能用非交互的方式传递密码,想不输入密码,直接ssh连接到服务器有两种方法,sshpass和expect sshpass # wget http://downloads.sourcefor ...

  3. java.lang.IllegalArgumentException: name MUST NOT NULL! at org.nutz.dao.impl.NutDao.fetch

    Nutz传值报错问题 作者:Vashon 时间:20150902 平台:Nutz框架 Java后台方法中拿值时报的错 报错信息: java.lang.IllegalArgumentException: ...

  4. (八)mybatis之映射器

    映射器 映射器是由Java接口和XML文件(或注解)共同组成的,作用如下: ①   定义参数类型. ②   描述缓存. ③   描述SQL语句. ④   定义查询结果和POJO的映射关系. 以下用两种 ...

  5. 通过90行代码学会HTML5 WebSQL的4种基本操作

    Web SQL数据库API是一个独立的规范,在浏览器层面提供了本地对结构化数据的存储,已经被很多现代浏览器支持了. 我们通过一个简单的例子来了解下如何使用Web SQL API在浏览器端创建数据库表并 ...

  6. 集成iAd广告

    在iPhone程序中集成广告,管他能不能赚钱,不放上一个iAd就心有不甘. 参考了下面这篇文章: http://bees4honey.com/blog/tutorial/how-to-add-iad- ...

  7. vue 不支持 数组Array,只支持get set push,但是正是做tab的时候,用到splice,就都不好用了,最后用v-if,从新渲染 完美解决

    vue 不支持 数组Array,只支持get set push,但是正是做tab的时候,用到splice,就都不好用了,最后用v-if,从新渲染 完美解决

  8. Arch Linux 天坑

    https://wiki.archlinux.org/index.php/Samba_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87) samba  gui客户端 smb4 ...

  9. PAT (Basic Level) Practise (中文)-1034. 有理数四则运算(20)

    PAT (Basic Level) Practise (中文)-1034. 有理数四则运算(20)  http://www.patest.cn/contests/pat-b-practise/1034 ...

  10. Java--返回类的对象(return this)

    如下代码所示: public Book getBook(){ return this; } 在getBook()方法中,方法的返回值为Book类,所以方法体中使用 return this 这种形式返回 ...