@topcoder - SRM614D1L3@ TorusSailing
@description@
给定一个 N*M 的方格图,某人从 (0, 0) 出发想要走到 (goalX, goalY)。
假如该人在 (x, y),他会等概率地走向 ((x + 1) mod N, y) 或 (x, (y + 1) mod M)。
求到达终点的期望步数。
@solution@
显然可以列出期望的 dp 方程 dp[x][y] = (dp[(x+1) mod N][y] + dp[x][(y+1) mod M])/2 + 1。
发现要用高斯消元,而普通的高斯消元 O(N^6) 的复杂度太高,无法通过。
注意到我们可以先人工合并一些方程。
具体操作是,保留一些量作为高斯消元的变量(此处我们选择与 (goalX, goalY) 同行与同列的量),将其视作常量。
然后利用转移图的特殊性质(此处转移图是个网格图),将其他量用这些量表示出来。
我们可以从 (goalX - 1, goalY - 1) 从下往上,自右往左依次得到其他量用这些量表示出来的结果。
这一部分的复杂度是 O(N^3),之后的高斯消元复杂度也为 O(N^3),我们就可以通过该题了。
@accepted code@
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
class TorusSailing{
private:
#define MAXN (200)
struct node{
double a[MAXN], b; int cnt;
node() {}
node(int n) {
cnt = n, b = 0;
for(int i=0;i<n;i++)
a[i] = 0;
}
friend node operator + (const node &x, const node &y) {
node z(x.cnt); z.b = x.b + y.b;
for(int i=0;i<x.cnt;i++) z.a[i] = x.a[i] + y.a[i];
return z;
}
friend node operator + (const node &x, const double &k) {
node z = x; z.b += k;
return z;
}
friend node operator / (const node &x, const double &k) {
node z(x.cnt); z.b = x.b / k;
for(int i=0;i<x.cnt;i++) z.a[i] = x.a[i]/k;
return z;
}
}a[MAXN][MAXN];
double A[MAXN][MAXN];
void gauss(int n, int m) {
int r = 0, c = 0;
while( r < n && c < m ) {
int mxr = r;
for(int i=r+1;i<n;i++)
if( fabs(A[i][c]) >= fabs(A[mxr][c]) )
mxr = i;
if( r != mxr ) {
for(int j=c;j<m;j++)
swap(A[r][j], A[mxr][j]);
}
if( A[r][c] ) {
double k = A[r][c];
for(int j=c;j<m;j++)
A[r][j] /= k;
for(int i=0;i<n;i++) {
if( i == r ) continue;
k = A[i][c];
for(int j=c;j<m;j++)
A[i][j] -= k*A[r][j];
}
r++;
}
c++;
}
}
public:
double expectedTime(int N, int M, int goalX, int goalY) {
int K = (N - 1) + (M - 1);
for(int i=0;i<N-1;i++)
a[i][M-1] = node(K), a[i][M-1].a[i] = 1;
for(int j=0;j<M-1;j++)
a[N-1][j] = node(K), a[N-1][j].a[j+N-1] = 1;
a[N-1][M-1] = node(K);
for(int j=M-2;j>=0;j--)
for(int i=N-2;i>=0;i--)
a[i][j] = (a[i+1][j] + a[i][j+1]) / 2 + 1;
for(int i=0;i<N-1;i++) {
node b = (a[i][0] + a[i+1][M-1]) / 2 + 1;
for(int j=0;j<K;j++) A[i][j] = -b.a[j];
A[i][i]++, A[i][K] = b.b;
}
for(int j=0;j<M-1;j++) {
node b = (a[0][j] + a[N-1][j+1]) / 2 + 1;
for(int i=0;i<K;i++) A[j+N-1][i] = -b.a[i];
A[j+N-1][j+N-1]++, A[j+N-1][K] = b.b;
}
gauss(K, K + 1);
int sx = N - goalX - 1, sy = M - goalY - 1;
double ans = a[sx][sy].b;
for(int i=0;i<a[sx][sy].cnt;i++)
ans += a[sx][sy].a[i] * A[i][K];
return ans;
}
};
@details@
事实上,这道题感觉和 PKUWC2018 那道高消的优化思路有点类似(用合并方程的思想逐渐把未知量消掉)。。。
不过也可能是我联想能力太强。。。
@topcoder - SRM614D1L3@ TorusSailing的更多相关文章
- TopCoder kawigiEdit插件配置
kawigiEdit插件可以提高 TopCoder编译,提交效率,可以管理保存每次SRM的代码. kawigiEdit下载地址:http://code.google.com/p/kawigiedit/ ...
- 记第一次TopCoder, 练习SRM 583 div2 250
今天第一次做topcoder,没有比赛,所以找的最新一期的SRM练习,做了第一道题. 题目大意是说 给一个数字字符串,任意交换两位,使数字变为最小,不能有前导0. 看到题目以后,先想到的找规律,发现要 ...
- TopCoder比赛总结表
TopCoder 250 500 ...
- Topcoder几例C++字符串应用
本文写于9月初,是利用Topcoder准备应聘时的机试环节临时补习的C++的一部分内容.签约之后,没有再进行练习,此文暂告一段落. 换句话说,就是本文太监了,一直做草稿看着别扭,删掉又觉得可惜,索性发 ...
- TopCoder
在TopCoder下载好luncher,网址:https://www.topcoder.com/community/competitive%20programming/ 选择launch web ar ...
- TopCoder SRM 596 DIV 1 250
body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } P ...
- 求拓扑排序的数量,例题 topcoder srm 654 div2 500
周赛时遇到的一道比较有意思的题目: Problem Statement There are N rooms in Maki's new house. The rooms are number ...
- TopCoder SRM 590
第一次做TC,不太习惯,各种调试,只做了一题...... Problem Statement Fox Ciel is going to play Gomoku with her friend ...
- Topcoder Arena插件配置和训练指南
一. Arena插件配置 1. 下载Arena 指针:http://community.topcoder.com/tc?module=MyHome 左边Competitions->Algorit ...
随机推荐
- 使用PHP得到所有的HTTP请求头
作者:老王 在PHP里,想要得到所有的HTTP请求头,可以使用getallheaders方法,不过此方法并不是在任何环境下都存在,比如说,你使用fastcgi方式运行PHP的话,就没有这个方法,所以说 ...
- js动态添加iframe,自适应页面宽高
function showIframe(url,w,h){ //添加iframe var if_w = w; var if_h = h; $("<iframe width='" ...
- LoadBalancer在kubernetes架构下的实践
Backgound 借助于kubernetes优秀的弹性扩缩功能,运行其中的应用程序能够在流量突增的时候坦然应对,在流量低谷的时候无需担心成本.但于此同时,也带来了极大的挑战: 弹性扩缩导致容器IP动 ...
- SQL——SQL日期
SQL日期 MySQL: NOW() 返回当前的日期和时间 CURDATE() 返回当前的日期 CURTIME() 返回当前的时间 DAT ...
- JS中的bind 、call 、apply
# 一 .bind 特点: ### 1.返回原函数的拷贝,我们称这个拷贝的函数为绑定函数 ### 2.将函数中的this固定为调用bind方法时的第一个参数,所以称之为绑定函数.注意是名词而非动词. ...
- 对 getopts 的理解
getopts 格式 1 #!/bin/bash 2 echo "begin index is $OPTIND" 3 echo "begin ARG is $OPTARG ...
- [C#] 使 ToolTip 一直显示 (在 WinForm 与 WPF 中的差异解决方案)
需求 自己绘制的UI,检测鼠标位置,适时显示出 ToolTip 1 WinForm 的 ToolTip // Member define: private ToolTip _toolTip = new ...
- [安卓基础] 001.学习Android开发的好教程
如果想自学android,有许多不错的android网站.这里收集了一些,列举如下: 国内 极客学院,这里有非常丰富的视频教程. http://www.jikexueyuan.com/course/a ...
- 如何发布一个 npm 包
一 背景 在工作时,突然接到经理的一个要求,需要将一个react的高阶组件函数封装成一个npm包.之前从没弄过,当场还是有些懵逼的,但是这毕竟是工作,不能推脱.于是开始了学习.汤坑之旅.最终包发布,线 ...
- SpringBoot实现微信小程序登录的完整例子
目录 一.登录流程 二.后端实现 1.SpringBoot项目结构树 2.实现auth.code2Session 接口的封装 3.建立用户信息表及用户增删改查的管理 4.实现登录认证及令牌生成 三.前 ...