• 【DP】AcWing 290. 坏掉的机器人


    分析

    这题不如说是一道数学题吧 hh。

    考虑倒推,假设现在已经求出了第 \(i+1\) 行的结果 \(c\),现在求第 \(i\) 行的结果,记为 \(y\)​,那么递推式为:

    \[\begin{aligned} \frac{2}{3} y_1 - \frac{1}{3}y_2 = \frac{1}{3}c_1 + 1 \\ \frac{2}{3} y_m - \frac{1}{3}y_{m-1} = \frac{1}{3}c_m + 1 \\ -\frac{1}{4} y_m + \frac{3}{4}y_{m-1} - \frac{1}{4}y_{m+1} = \frac{1}{4}c_j + 1 &&& j\in[2,m-1] \end{aligned} \]

    递推的边界是第 \(n\) 行,此时的 \(c\) 值都是 \(0\)

    写成 \(m\times m\) 的矩阵就是(以 \(m=3\) 为例):

    \[\begin{pmatrix} \frac{2}{3} & -\frac{1}{3} & 0 \\ -\frac{1}{4} & \frac{3}{4} & -\frac{1}{4} \\ 0 & -\frac{1}{3} & \frac{2}{3} \\ \end{pmatrix} \begin{pmatrix} y_1 \\ y_2 \\ y_3 \end{pmatrix} = \begin{pmatrix} \frac{1}{3} c_1 + 1 \\ \frac{1}{4} c_2 + 1 \\ \frac{1}{3} c_3 + 1 \end{pmatrix} \]

    那么进行高斯消元并求出 \(y\) 即可。

    当然,因为这个矩阵比较特殊,我们不需要而且也不能直接用普通的高斯消元(复杂度 \(O(n^3)\)),注意到这个矩阵化成上三角矩阵的代价只需要 \(O(n)\),类似地,化为对角矩阵的代价也是 \(O(n)\),所以整个过程 \(O(n)\) 即可完成。

    这题有一个边界问题:\(m=1\) 的情况,上面的递推式显然不正确,在原做法上修改过于复杂,所以我们将其作为一个小问题解决:

    给你一个数轴,从 \(0\) 出发,问到点 \(i\) 的期望步数是多少?

    那么我们有 \(y_i = \frac{1}{2}(y_i + y_{i-1}) + 1\),化简得 \(y_i = y_{i-1} + 2\),首项自然是 \(0\),故通项公式为 \(y_i = 2i\)。​

    实现

    主体部分 30 行,很短的 qwq~。

    // Problem: 坏掉的机器人
    // Contest: AcWing
    // URL: https://www.acwing.com/problem/content/description/292/
    // Memory Limit: 64 MB
    // Time Limit: 1000 ms
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    #include<bits/stdc++.h>
    using namespace std;
    
    #define debug(x) cerr << #x << ": " << (x) << endl
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define dwn(i,a,b) for(int i=(a);i>=(b);i--)
    
    const int N=1010;
    
    int n, m;
    int tx, ty;
    double y[N], c[N];
    
    double w[N][N];
    void get(){
    	rep(j,1,m){
    		if(j==1 || j==m) c[j]=1.0/3*c[j]+1;
    		else c[j]=1.0/4*c[j]+1;
    	}
    
    	w[1][1]=2.0/3, w[1][2]=-1.0/3;
    	w[m][m-1]=-1.0/3, w[m][m]=2.0/3;
    	rep(i,2,m-1) w[i][i]=3.0/4, w[i][i-1]=w[i][i+1]=-1.0/4;
    	rep(i,2,m){
    		double k=w[i][i-1]/w[i-1][i-1];
    		rep(j,i-1,i) w[i][j]-=k*w[i-1][j]; 
    		c[i]-=k*c[i-1];
    	}
    	dwn(i,m-1,1){
    		double k=w[i][i+1]/w[i+1][i+1];
    		w[i][i+1]=0;
    		c[i]-=k*c[i+1];
    	} 
    	rep(j,1,m) y[j]=c[j]/w[j][j], c[j]=y[j];
    }
    
    int main(){
    	cin>>n>>m>>tx>>ty;
    	rep(i,1,m) c[i]=0;
    	
    	int tot=n-tx;
    	if(m==1) return printf("%.4lf\n", 2.0*tot), 0;
    	while(tot--) get();
    	printf("%.4lf\n", c[ty]);
    	return 0;
    }
    
  • 相关阅读:
    BeautifulSoup的基本用法
    [leedcode 189] Rotate Array
    [leedcode 187] Repeated DNA Sequences
    [leedcode 179] Largest Number
    [leedcode 174] Dungeon Game
    [leedcode 173] Binary Search Tree Iterator
    [leedcode 172] Factorial Trailing Zeroes
    [leedcode 171] Excel Sheet Column Number
    [leedcode 169] Majority Element
    [leedcode 168] Excel Sheet Column Title
  • 原文地址:https://www.cnblogs.com/Tenshi/p/15963731.html
Copyright © 2020-2023  润新知