@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. 树状数组区间更新区间查询以及gcd的logn性质

    题目描述 给你一个长为n的序列a m次查询 每次查询一个区间的所有子区间的gcd的和mod1e9+7的结果 输入描述: 第一行两个数n,m之后一行n个数表示a之后m行每行两个数l,r表示查询的区间 输 ...

  2. 【git】git 常用命令(含删除文件)

    Git常用操作命令收集: 1) 远程仓库相关命令 检出仓库:$ git clone git://github.com/jquery/jquery.git 查看远程仓库:$ git remote -v ...

  3. vue脚手架3.0的安装与使用

    一.安装 1.先检查是否有安装vue  (vue-cli3需要node大于等于8.9版本) //vue -V 2.如果没安装跳过.安装有3.0以下的版本就的先卸载掉以前的版本 npm uninstal ...

  4. Java——关键字instanceof

    instanceof 判断一个对象是否为一个类的实例,是为true ,否为false class Animal{} class Cat extends Animal{} /**instanceof 判 ...

  5. pytest跳过指定的测试或模块

    参考Allure官方文档,pytest官方文档 实现setup/teardown 1.运行带指定标记的测试 @pytest.mark.tags ,这里的tags可以自定义 命令行执行:pytest - ...

  6. PHP相关_几个操作记录下

    1.JSON转换 var cloneTesttaskList = <?php echo json_encode(json_encode($cloneTesttaskList));?>; v ...

  7. [PHP学习教程 - 文件]002.修改上传文件大小限制(File Upload Limit)

    引言:通常大家直装xampp之后,默认的文件上传大小应该被设定成2M左右,这个时候如果上传超过2M的东西,就会报错,让人非常尴尬.如何修改呢? 导航索引: 概念 FTP常用API FTP封装类 其他 ...

  8. DataFrame迭代过程中多行修改

    方法1:df.loc[conditions]=row.values,逐行地进行整行替换 for row in df.iterrows(): row['given_amount']=row['amoun ...

  9. Rocket - diplomacy - AddressDecoder

    https://mp.weixin.qq.com/s/UHGq74sEd9mcG5Q3f-g3mA   介绍AddressDecoder的实现.   ​​ 1. 基本定义   ​​ 每个Port包含多 ...

  10. Dubbo源码笔记-服务注册

    今天来简单做一下Dubbo服务注册部分源码学习手记. 一.Dubbo配置解析 目前Dubbo最多的用法就是跟Spring集成,既然跟Spring集成,那么,Dubbo对象的实例化都将交由Spring统 ...