1. 程式人生 > 實用技巧 >Broken robot CodeForces - 24D (三對角矩陣簡化高斯消元+概率dp)

Broken robot CodeForces - 24D (三對角矩陣簡化高斯消元+概率dp)

題意:

有一個N行M列的矩陣,機器人最初位於第i行和第j列。然後,機器人可以在每一步都轉到另一個單元。目的是轉到最底部(第N個)行。機器人可以停留在當前單元格處,向左移動,向右移動或移動到當前位置下方的單元格。如果機器人在最左側的列中,則不能向左移動;如果機器人在最右側的列中,則不能向右移動。在每一步中,所有可能的移動都是同等可能的。返回到達最底行的預期步數。

程式碼+題解:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include
<iostream> using namespace std; #define mem(a) memset(a,0,sizeof(a)) #define mem__(a) memset(a,-1,sizeof(a)) typedef long long ll; const int maxn=1e3+10; const int N=200; const int INF=0x3f3f3f3f; const double blo=1.0/3.0; const double eps=1e-8; double dp[maxn][maxn],a[maxn][maxn],b[maxn]; int main() {
int x,y,n,m; scanf("%d%d",&n,&m); scanf("%d%d",&x,&y); mem(dp); if(m==1) { printf("%.4lf\n",2.0*(n-x)); return 0; } /* dp[i][1]-1/2dp[i][2]=3/2+1/2dp[i+1][1] -1/4dp[i][j-1]+3/4dp[i][j]-1/4dp[i][j+1]=1+1/4dp[i+1][j],1<j<m -1/2dp[i][m-1]+dp[i][m]=3/2+1/2dp[i+1][m]
*/ for(int i=n-1; i>=1; --i) { /* 構造一個矩陣 x1 x2 x3...xn 代表的是未知變數dp[i][j]前面的係數,這個係數放在a數組裡面 由上面三個公式就是分別求dp[i][1]和dp[i][j]和dp[i][m]的公式 dp[i][1]需要用到前兩個變數dp[i][2]和dp[i+1][1] dp[i][j]就需要用到變數dp[i][j-1],dp[i][j+1],dp[i+1][j] dp[i][m]需要用到前兩個變數dp[i][m-1]和dp[i+1][m] 那麼它們的係數就會構造一個下面這樣的矩陣 x x 0 0 0 這一行中我們設第一個x為x1,另一個為x2.那麼x1=1.0,x2=-1/2 ,b[1]= 3/2+1/2dp[i+1][1],b陣列下面有解釋 x x x 0 0 0 x x x 0 0 0 x x x 0 0 0 x x 這個矩陣肯定是一個正方形,因為n個未知數需要n個方程,所以肯定矩陣是一個正方形矩陣 另外我們還需要一個b陣列來儲存這n個方程右邊的值,這個右邊的值是不含未知數,所以是一個已知值
     之後就是高斯消元部分: 我們可以通過方程之間的加減乘除來使這個係數矩陣變成 x x 0 0 0 0 x x 0 0 0 0 x x 0 0 0 0 x x 0 0 0 0 x 然後我們再化簡成 x 0 0 0 0 0 x 0 0 0 0 0 x 0 0 0 0 0 x 0 0 0 0 0 x 這個樣子的話就變成了一元一次方程,那麼一層for迴圈就可以求出來所有未知量的值
*/ for(int j=2; j<m; ++j) { a[j][j]=-1*3.0/4.0; a[j][j-1]=1.0/4.0; a[j][j+1]=1.0/4.0; b[j]=-1.0-1.0/4.0*dp[i+1][j]; } if(m>=2) { a[m][m] = a[1][1] = -2.0 / 3; a[1][2] = a[m][m - 1] = 1.0 / 3; b[1] = -1 - dp[i + 1][1] / 3.0; b[m] = -1 - dp[i + 1][m] / 3.0; } for(int j = 1; j < m; j++) { if(fabs(a[j+1][j])< eps) continue; double rate = a[j + 1][j] / a[j][j]; for(int k = 0; k < 2; k++) a[j + 1][j + k]-=a[j][j + k]*rate; b[j + 1]-=b[j]*rate; } for(int j = m; j > 1; j--) { if(fabs(a[j - 1][j]) < eps) continue; double rate = a[j - 1][j] / a[j][j]; a[j - 1][j] -= a[j][j] * rate; b[j - 1] -= b[j] * rate; } for(int j=1;j<=m;++j) dp[i][j]=b[j]/a[j][j]; } printf("%.4lf\n",dp[x][y]); return 0; }