日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【高斯消元】兼 【期望dp】例题

發布時間:2025/6/17 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【高斯消元】兼 【期望dp】例题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【總覽】

高斯消元基本思想是將方程式的系數和常數化為矩陣,通過將矩陣通過行變換成為階梯狀(三角形),然后從小往上逐一求解。

如:$3X_1 + 2X_2 + 1X_3 = 3$

  $ ? ? ? ? ? ? ?X_2 + 2X_3 = 1$

  $2X_1 + X_3 = 0$

化為矩陣為:--->----->----->

然后就可以通過最后一行直接求出$X_3 = ...$,將其帶回第二行,算出$X_2$,同理算出$X_1$。

代碼很好理解:

inline void gauss(){int i, j, k, l;for(i = 1; i <= n; i++){l = i;for(j = i + 1; j <= n; j++)if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;if(l != i) for(j = i; j <= n + 1; j++)swap(matrix[i][j], matrix[l][j]);for(j = i + 1; j <= n; j++){double tmp = matrix[j][i] / matrix[i][i];for(k = i; k <= n + 1; k++)matrix[j][k] -= matrix[i][k] * tmp;}}for(i = n; i >= 1; i--){double t = matrix[i][n + 1];for(j = n; j > i; j--)t -= ans[j] * matrix[i][j];ans[i] = t / matrix[i][i];} }

?高斯消元最常應用在 ?期望DP ?中。下面是幾道例題。

“期望dp講解及例題”

【BZOJ1013】球形空間產生器sphere

由給出的$n + 1$個坐標,可以列出 $n$個方程,剩下的模板。

【CODE】

#include<iostream> #include<cstring> #include<string> #include<cstdio> #include<cstdlib> #include<algorithm> #include<vector> #include<cmath> using namespace std;const int N = 20; double matrix[N][N], last[N], t, ans[N]; int n;inline int read(){int i = 0, f = 1; char ch = getchar();for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());if(ch == '-') f = -1, ch = getchar();for(; ch >= '0' && ch <= '9'; ch = getchar())i = (i << 3) + (i << 1) + (ch -'0');return i * f; }inline void wr(int x){if(x < 0) putchar('-'), x = -x;if(x > 9) wr(x / 10);putchar(x % 10 + '0'); }inline void gauss(){int i, j, l, k;for(i = 1; i <= n; i++){l = i;for(j = i + 1; j <= n; j++) if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;if(l != i) for(j = i; j <= n + 1; j++)swap(matrix[i][j], matrix[l][j]);for(j = i + 1; j <= n; j++){double tmp = matrix[j][i] / matrix[i][i];for(k = i; k <= n + 1; k++) matrix[j][k] -= matrix[i][k] * tmp;}}for(i = n; i >= 1; i--){double tmp = matrix[i][n + 1];for(j = n; j > i; j--)tmp -= ans[j] * matrix[i][j];ans[i] = tmp / matrix[i][i];} }int main(){n = read();for(int i = 1; i <= n; i++) scanf("%lf", &last[i]);for(int i = 1; i <= n; i++){t = 0;for(int j = 1; j <= n; j++){double tmp; scanf("%lf", &tmp);matrix[i][j] = 2 * (tmp - last[j]);t += tmp * tmp - last[j] * last[j];last[j] = tmp;}matrix[i][n + 1] = t;}gauss();for(int i = 1; i <= n; i++){if(i < n) printf("%.3lf ", ans[i]);else printf("%.3lf\n", ans[i]);}return 0; }

【BZOJ3143】游走

  因為要求期望的最小值,那么走的次數多的邊肯定要讓花費(編號)盡可能小,所以可以先求出從每個點出發次數的期望值$E_i$,那么對于一條邊而言,走這條邊的期望次數就是$E_i / degree[i] + E_j / degree[j]$,只要排一遍序就好。

  求點的期望:$E_i = \sum (E_{son[i]} / degree[i])$

【code】

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector> #define eps 1e-10 using namespace std;const int N = 600; double matrix[N][N], ans[N], ret; int n, m, num, degree[N]; int st[500000], ed[500000]; double gg[500000];inline void addEdge(const int &u, const int &v){degree[u]++;degree[v]++;st[++num] = u, ed[num] = v; }inline int read(){int i = 0, f = 1; char ch = getchar();for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());if(ch == '-') f = -1, ch = getchar();for(; ch >= '0' && ch <= '9'; ch = getchar())i = (i << 3) + (i << 1) + (ch -'0');return i * f; }inline void gauss(){int i, j, l, k;for(i = 1; i <= n; i++){l = i;for(j = i + 1; j <= n; j++) if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;if(l != i) for(j = i; j <= n + 1; j++)swap(matrix[i][j], matrix[l][j]);for(j = i + 1; j <= n; j++){double tmp = matrix[j][i] / matrix[i][i];for(k = i; k <= n + 1; k++) matrix[j][k] -= matrix[i][k] * tmp;}}for(i = n; i >= 1; i--){double tmp = matrix[i][n + 1];for(j = n; j > i; j--)tmp -= ans[j] * matrix[i][j];ans[i] = tmp / matrix[i][i];} }inline bool cmp (double a, double b){return a > b; }int main(){n = read(), m = read();for(int i = 1; i <= m; i++){int u = read(), v = read();addEdge(u, v);}int i, j;for(i = 1; i <= m; i++){matrix[st[i]][ed[i]] += 1.0 /degree[ed[i]];matrix[ed[i]][st[i]] += 1.0 /degree[st[i]];}for(i = 1; i <= n; i++) matrix[n][i] = 0; for(i = 1; i <= n; i++) matrix[i][i] = -1.0;matrix[1][n + 1] = -1.0;gauss();for(i = 1; i <= m; i++)gg[i] = ans[st[i]] / degree[st[i]] + ans[ed[i]] / degree[ed[i]];sort(gg + 1, gg + m + 1, cmp);for(i = 1; i <= m; i++) ret += gg[i] * i;printf("%.3f\n", ret);return 0; }

?【bzoj2337】XOR和路徑

  學到了!看見求異或和$----->$按位計算:即一位一位的計算答案每一位上為1的期望值,這樣就可以輕松統計出答案。

  每一位都要重新構造矩陣求期望,設$a[i]$表示從$i$到$n$的路徑異或和(這一位)為$1$的期望概率(總是≤$1$)

  對于當前第$i + 1$位,若$(dis >> i) \& 1$(這一位為1),那么要異或和為$1$,要求他從關聯點異或和為$0$轉移來,

  同理,若這一位為$0$,要求從$1$轉移來。即:$$a[i] = \sum a[son[i]](dis這一位為0) / degree[i] ?+ \sum a[son[i]](dis這一位為1) / degree[i]$$。

【code】

#include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cmath> using namespace std;const int N = 105, M = 10005; int n, m; int ecnt, st[M << 1], ed[M << 1], len[M << 1], degree[N]; double matrix[N][N], ans[N], ret;inline void addEdge(const int &u, const int &v, const int &l){st[++ecnt] = u, ed[ecnt] = v, len[ecnt] = l; degree[u]++;if(u != v) st[++ecnt] = v, ed[ecnt] = u, len[ecnt] = l, degree[v]++; }inline void gauss(){int i, j, k, l;for(i = 1; i <= n; i++){l = i;for(j = i + 1; j <= n; j++)if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;if(l != i) for(j = i; j <= n + 1; j++)swap(matrix[i][j], matrix[l][j]);for(j = i + 1; j <= n; j++){double tmp = matrix[j][i] / matrix[i][i];for(k = i; k <= n + 1; k++)matrix[j][k] -= matrix[i][k] * tmp;}}for(i = n; i >= 1; i--){double t = matrix[i][n + 1];for(j = n; j > i; j--)t -= ans[j] * matrix[i][j];ans[i] = t / matrix[i][i];} }int main(){scanf("%d%d", &n, &m);int i, j, k;for(i = 1; i <= m; i++){int u, v, w; scanf("%d%d%d", &u, &v, &w);addEdge(u, v, w);}for(i = 0; i <= 30; i++){memset(matrix, 0, sizeof matrix);memset(ans, 0, sizeof ans);for(j = 1; j <= n; j++) matrix[j][j] = 1;for(j = 1; j <= ecnt; j++){int l = len[j], u = st[j], v = ed[j];if(u == n) continue;if((l >> i) & 1){matrix[u][v] += 1.0 / degree[u];matrix[u][n + 1] += 1.0 / degree[u];}else matrix[u][v] -= 1.0 / degree[u];}gauss();ret += ans[1] * (1 << i);}printf("%.3f\n", ret);return 0; }

轉載于:https://www.cnblogs.com/CzYoL/p/7226719.html

總結

以上是生活随笔為你收集整理的【高斯消元】兼 【期望dp】例题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。