[lnsyoj4079/luoguP6899]Pachinko

题意

一个包括空地、障碍和空洞的 \(H\times W\) 地图,从第一列随机选取空地作为起始位置,到达某个空洞后停止运动。给定向上下左右移动的概率比 \(p_u:p_d:p_l:p_r\),求在每个空洞停止运动的概率为多少。

sol

由于每次到达空洞后即会停止运动,因此到达空洞的期望次数即为到达每个空洞的概率。记 \(f_{i,j}\) 表示到达 \((i,j)\) 的次数的期望,就可以很容易的推出转移方程:

\[f_{i,j}= f_{i+1,j}\cdot \frac{p_u}{psum} + f_{i-1,j}\cdot \frac{p_d}{psum} + f_{i,j+1}\cdot \frac{p_l}{psum} + f_{i,j -1}\cdot\frac{p_r}{psum} + [i=1]\cdot \frac{1}{stcnt} \]

\(stcnt\) 为第一行空地的数量,\(psum\) 为可以转移到的方向的概率比之和)

需要注意一点:当出现某一列全为 \(0\) 无法消元时,对答案并无影响,因此 continue 即可。

这样,我们只需要对列出的方程进行高斯消元即可解出答案……吗?

我们发现,这样一来,我们所求的未知数数量为 \(HW\) 个,而高斯消元的复杂度是 \(O(n^3)\) 的,因此时间复杂度就达到了 \(O((HW)^3)\),空间复杂度达到了 \(O((HW)^2)\),无法接受。

不过,我们的增广矩阵中,最多只会在对角线左右 \(\pm W\) 的位置出现非零数字,这是一个非常经典的优化 band-matrix。在消元和回代时,只向后修改 \(W\) 列即可,即使是矩阵中出现 \(0\),需要换行时,也最多只需修改 \((2W)\times (2W)\) 的矩阵即可,而不需要修改整个矩阵;而且,我们可以为每一个可能出现非零数字的位置记录一个偏移量,这样时间复杂度就优化到了 \(O(HW^3)\),空间复杂度优化到了 \(O(HW^2)\)

注意:如果 \(\color{red}{\text{WA}}\) on #9, Line 13,说明是被卡精度了;如果结果输出了 -nan,请改变写法,不要直接使用 \(i*m+j\) 作为编号存储,而是对每一个非障碍方格进行编号。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>using namespace std;const int N = 25, M = 10005;
const long double eps = 1e-10;int n, m, p[4];
int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
int pfrom[4] = {1, 0, 3, 2};
long double coeff[N * M][N * 4];
long double ans[N * M];
int psum[N * M];
int id[M][N];
char g[M][N];
int idx;long double &c(int a, int b){return coeff[a][b - max(0, a - 2 * m)];
}void gauss(){for (int i = 1; i <= idx; i ++ ){if (abs(c(i, i)) <= eps) continue;int ed = min(idx, i + 2 * m);ans[i] /= c(i, i);for (int j = ed; j >= i; j -- )c(i, j) /= c(i, i);for (int j = i + 1; j <= min(i + m, idx); j ++ ){ ans[j] -= c(j, i) * ans[i];for (int k = ed; k >= i; k -- ) c(j, k) -= c(j, i) * c(i, k);}}for (int i = idx; i; i -- ){for (int j = i + 1; j <= min(idx, i + 2 * m); j ++ )ans[i] -= c(i, j) * ans[j];}
}int main(){scanf("%d%d", &m, &n);for (int i = 0; i < 4; i ++ ) scanf("%d", &p[i]);for (int i = 0; i < n; i ++ ) scanf("%s", g[i]);int stcnt = 0;for (int i = 0; i < m; i ++ ) stcnt += (g[0][i] == '.');for (int i = 0; i < n; i ++ )for (int j = 0; j < m; j ++ ){id[i][j] = (g[i][j] == 'X') ? -1 : ++ idx;if (id[i][j] == -1) continue;for (int u = 0; u < 4; u ++ ) {int sx = i + dx[u], sy = j + dy[u];if (sx < 0 || sx >= n || sy < 0 || sy >= m || g[sx][sy] == 'X') continue;psum[id[i][j]] += p[u];}}for (int i = 0; i < n; i ++ )for (int j = 0; j < m; j ++ ){if (id[i][j] == -1) continue;if (!i && g[i][j] == '.') ans[id[i][j]] = (long double) 1 / stcnt;for (int u = 0; u < 4; u ++ ){int sx = i + dx[u], sy = j + dy[u];int px = pfrom[u];if (sx < 0 || sx >= n || sy < 0 || sy >= m || g[sx][sy] == 'X' || g[sx][sy] == 'T') continue;int sid = id[sx][sy];c(id[i][j], sid) = (long double) -p[px] / psum[sid];}c(id[i][j], id[i][j]) = 1;}gauss();for (int i = 0; i < n; i ++ )for (int j = 0; j < m; j ++ )if (g[i][j] == 'T') printf("%.9Lf\n", ans[id[i][j]]);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/783348.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pbootcms 网站打开提示:未检测到您服务器环境的sqlite3数据库扩展...

pbootcms 网站打开提示:未检测到您服务器环境的sqlite3数据库扩展...按照提示信息操作,检查php.ini中是否已经开启sqlite3扩展。详细介绍->pbootcms提示错误信息 未检测到您服务器环境的sqlite3数据库扩展扫码添加技术【解决问题】专注中小企业网站建设、网站安全12年。熟…

Python网页应用开发神器fac 0.3.0全新版本发布

大家好我是费老师,在Python生态中,有很多以Python为主要开发语言,实现网页应用开发的框架,其中最为知名的有Dash、flet、streamlit、gradio、nicegui等。 如果综合考虑流行度、开发效率、开发自由度、相关生态成熟度、可拓展性、安全性等各方面的能力,Dash是其中天花板级别…

天线选择快速指导

《swra351b-DN035 -- Antenna Quick Guide (Rev. B).pdf》

pbootcms新手必读|安装需知|环境要求|快速部署|获取授权码|模板制作

环境要求服务器:Linux / Windows / Nginx / Apache / IIS PHP版本:不小于5.4,完美支持php7。推荐PHP5.6和PHP7.3 MYSQL版本:5.0以上。推荐使用5.5+快速部署1、将官网下载的压缩包里面所有文件和文件夹上传到你的网站根目录 (支持安装在二级目录)2、数据库默认采用的是sqlit…

pbootcms教程—设置的会话目录创建失败!

pbootcms教程&mdash;设置的会话目录创建失败!这个问题常见于宝塔面板,用户将pbootcms模板传到宝塔上,打开域名出现这个问题。解决方法:1、打开宝塔面板,左侧找到文件,找到对应的站点目录,如下图:2、按照下图进行设置,点确定,如果默认就是这样的设置,也要点下确定…

pbootcms模板自动清理runtime缓存

打开/apps/home/controller/ExtLabelController.php文件找到// 测试扩展单个标签 private function test() { $this->content = str_replace({pboot:userip}, get_user_ip(), $this->content); }}在它下面加入 // 自动会话清理脚本public function clean…

使用Github Action来拉取docker镜像

前提 只需一个github账号即可注意: 免费版 Action 每天能使用1小时,每个月33小时(基本上够用) 国内网络访问github网速并不稳定,但是用来应急还是可以的拉取逻辑GitHub Action 来拉取和打包镜像 从 github 上下载压缩包 上传到自己的服务器上 解压加载镜像到自己的服务器上…

zabbix“专家坐诊”第251期问答

问题一 Q:zabbix模板自带的监控项很多都不需要,也不用删除,就是怎么让他们都不展示出来A:禁用掉 Q:还是在的,我想要就看不见,不是不启用,想要效果跟删除一样,看不见,不会妨碍浏览,这些自带的模板很多都很废 A:是指标列表不想看到还是这个地方不想看到 问题二 Q:z…

使用一次sql语句,返回分页数据和总条数

日常搬砖,总少不了需要获取分页数据和总行数。 一直以来的实践是编码两次sql请求,分别拉分页数据和totolCount。 最近我在思考: 常规实践为什么不是 在一次sql请求中中执行多次sql查询或多次更新,显而易见的优势: ① 能显著减低“客户端和服务器之间的网络往返次数”,提高…

API 设计 实践

深度 | API 设计最佳实践的思考 https://mp.weixin.qq.com/s/qWrSyzJ54YEw8sLCxAEKlA深度 | API 设计最佳实践的思考 谷朴 阿里云开发者 2019年05月09日 08:10阿里妹导读:API 是模块或者子系统之间交互的接口定义。好的系统架构离不开好的 API 设计,而一个设计不够完善的 API…

关于并查集

关于冰茶姬关于冰茶姬 简述 冰茶姬是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节点表示对应集合中的元素。 顾名思义,冰茶姬支持两种操作:合并(Union):合并两个元素所属集合(合并对应的树)查询(Find):查询某个元素所属集…

Cookie、localStorage 和 sessionStorage 的区别及应用实例

在前端开发中,持久化数据存储是一个非常常见的需求。为了实现这一点,浏览器提供了多种方式,包括 Cookie、localStorage 和 sessionStorage。这三者各有优劣,适用于不同的场景 1. Cookie Cookie 是浏览器存储少量数据的一种机制,通常由服务器生成并发送到客户端。每次客户端…