@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 ...
随机推荐
- 计算程序运行时间(.net1.1 于.net2.0的区别)在.net2.0中提供了Stopwatch类,简单例子
1. [代码].NET 2.0 using System.Diagnostics; private Stopwatch stw = new Stopwatch(); private void ...
- Intel FPGA Clock Region概念以及用法
目录 Intel FPGA 的Clock Region概念 Intel 不同系列FPGA 的Clock Region 1. Clock Region Assignments in Intel Stra ...
- linux DRM/KMS 测试工具 modetest、kmscude、igt-gpu-tools (二)
kmscube kmscube is a little demonstration program for how to drive bare metal graphics without a c ...
- 解决2003 - 2003 - Can't connect to MySQL server on '127.0.0.1'(61 "Connection refused")
1)右击数据库选择编辑连接2) 3)重新输入密码即可
- HTML开发实例-简单相亲网站开发(主体为table)
实现功能:简单的相亲网站: 清楚不常在,抓紧谈恋爱 我承诺 年满十八岁 单身 抱着严肃态度 寻找真诚的另一半 性别: 男 女 生日: --请选择年-- 2019 2020 2021 --请选择月-- ...
- vue中 transition组件使用总结
博客园比较啃爹啊,随笔只能手写,之前写在有道云笔记里面的内容也复制不了,忧伤..... 长话短说,看官方的transition 的讲解,可能是内容太多了,或者就是本人太辣鸡了,看的有点懵逼,但是项目中 ...
- super调用父类的属性方法
super:可以用来修饰属性 方法 构造器 当子类与父类中有同名的属性时,可以通过 super.此属性 显式的调用父类声明的属性 若想调用子类的同名的属性“this.此属性” 2.当子类重 ...
- 二、React初体验之React组件创建
(中间因为应付各种考试,处理其他事情,隔了好时间没更新,现在终于有时间了,续上!) 本文为React初始体验,因此先不考虑文件如何组织,尽量以最简单的方式让大家了解React其中的原理. 在创建组件( ...
- 10 个提高效率的 Linux 命令别名
在 Linux 环境下工作的工程师,一定会对那些繁琐的指令和参数命令行印象深刻吧.而且,可怕的不是繁琐,而是需要大量重复输入这些繁琐的命令. 在 Linux 下我们有个别名命令 alias ,可以将那 ...
- win10和centos7双系统双磁盘引导的实现
win10和centos7双系统双磁盘引导的实现1.背景:dell5460笔记本电脑M2-120G固态盘无法在bios中引导,新装了M360G固态盘后,考虑把120G固态盘安装centos7.5系统做 ...