@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的更多相关文章

  1. TopCoder kawigiEdit插件配置

    kawigiEdit插件可以提高 TopCoder编译,提交效率,可以管理保存每次SRM的代码. kawigiEdit下载地址:http://code.google.com/p/kawigiedit/ ...

  2. 记第一次TopCoder, 练习SRM 583 div2 250

    今天第一次做topcoder,没有比赛,所以找的最新一期的SRM练习,做了第一道题. 题目大意是说 给一个数字字符串,任意交换两位,使数字变为最小,不能有前导0. 看到题目以后,先想到的找规律,发现要 ...

  3. TopCoder比赛总结表

    TopCoder                        250                              500                                 ...

  4. Topcoder几例C++字符串应用

    本文写于9月初,是利用Topcoder准备应聘时的机试环节临时补习的C++的一部分内容.签约之后,没有再进行练习,此文暂告一段落. 换句话说,就是本文太监了,一直做草稿看着别扭,删掉又觉得可惜,索性发 ...

  5. TopCoder

    在TopCoder下载好luncher,网址:https://www.topcoder.com/community/competitive%20programming/ 选择launch web ar ...

  6. TopCoder SRM 596 DIV 1 250

    body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } P ...

  7. 求拓扑排序的数量,例题 topcoder srm 654 div2 500

    周赛时遇到的一道比较有意思的题目: Problem Statement      There are N rooms in Maki's new house. The rooms are number ...

  8. TopCoder SRM 590

     第一次做TC,不太习惯,各种调试,只做了一题...... Problem Statement     Fox Ciel is going to play Gomoku with her friend ...

  9. Topcoder Arena插件配置和训练指南

    一. Arena插件配置 1. 下载Arena 指针:http://community.topcoder.com/tc?module=MyHome 左边Competitions->Algorit ...

随机推荐

  1. canvas遇到的一些问题

    1.移动端无法全屏问题 问题描述:由于canvas的width和height只能设置px值,不支持rem单位,所以想在移动设备屏幕分辨率繁杂的情况下达到canvas铺满全屏的效果很困难. 解决方法:通 ...

  2. oracle start with

    select * from t where 1=1 START WITH key_id=600 CONNECT BY PRIOR key_id = pid order by key_id desc

  3. C# 数据操作系列 - 13 SugarSql初探

    0. 前言 前言,暂时挥别NHibernate(虽然我突然发现这玩意还挺有意思的,不过看得人不多).大步进入了有很多小伙伴向我安利的SQLSugar,嗯,我一直叫SugarSQL,好像是这个吧? 这是 ...

  4. Hyperledger Fabric Node SDK和应用开发

    Hyperledger Fabric 提供了多种语言的SDK版本,其中提出比较早.比较稳定而全面的是Node.js版本的SDK. 前面提到的fabric示例(如first-network和e2e-cl ...

  5. Python3高级核心技术97讲

    可以毫不夸张的说:这门课程是初中级Python开发人员向高级进阶的必学课程 许多Pythoner喜欢追求新的框架,但却不重视Python本身基础知识的学习, 他们不知道的是,语言本身的进阶优先于框架, ...

  6. Socket - TCP编程

    Socket是网络编程的一个抽象概念. 通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可 socket参数及常用功能 ...

  7. Algorithms - Data Structure - Perfect Hashing - 完全散列

    相关概念 散列表 hashtable 是一种实现字典操作的有效数据结构. 在散列表中,不是直接把关键字作为数组的下标,而是根据关键字计算出相应的下标. 散列函数 hashfunction'h' 除法散 ...

  8. 写给程序员的机器学习入门 (五) - 递归模型 RNN,LSTM 与 GRU

    递归模型的应用场景 在前面的文章中我们看到的多层线性模型能处理的输入数量是固定的,如果一个模型能接收两个输入那么你就不能给它传一个或者三个.而有时候我们需要根据数量不一定的输入来预测输出,例如文本就是 ...

  9. Android_存储之SharedPreferences

    一.概述 SharedPreferences是一种轻量级的数据存储方式,采用键值对的存储方式. SharedPreferences只能存储少量数据,大量数据不能使用该方式存储,支持存储的数据类型有bo ...

  10. HotRing: A Hotspot-Aware In-Memory Key-Value Store(FAST ’20)

      本文主要解决的是基于内存的K-V存储引擎在实际应用中出现的热点问题,设计了一个热点可感知的KV存储引擎,极大的提升了KV存储引擎对于热点数据访问的承载能力. Introduction 热点问题,可 ...