【高斯消元】兼 【期望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 = ; i <= n; i++){
l = i;
for(j = i + ; j <= n; j++)
if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;
if(l != i) for(j = i; j <= n + ; j++)
swap(matrix[i][j], matrix[l][j]);
for(j = i + ; j <= n; j++){
double tmp = matrix[j][i] / matrix[i][i];
for(k = i; k <= n + ; k++)
matrix[j][k] -= matrix[i][k] * tmp;
}
}
for(i = n; i >= ; i--){
double t = matrix[i][n + ];
for(j = n; j > i; j--)
t -= ans[j] * matrix[i][j];
ans[i] = t / matrix[i][i];
}
}
高斯消元最常应用在 期望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 = ;
double matrix[N][N], last[N], t, ans[N];
int n; inline int read(){
int i = , f = ; char ch = getchar();
for(; (ch < '' || ch > '') && ch != '-'; ch = getchar());
if(ch == '-') f = -, ch = getchar();
for(; ch >= '' && ch <= ''; ch = getchar())
i = (i << ) + (i << ) + (ch -'');
return i * f;
} inline void wr(int x){
if(x < ) putchar('-'), x = -x;
if(x > ) wr(x / );
putchar(x % + '');
} inline void gauss(){
int i, j, l, k;
for(i = ; i <= n; i++){
l = i;
for(j = i + ; j <= n; j++)
if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;
if(l != i) for(j = i; j <= n + ; j++)
swap(matrix[i][j], matrix[l][j]);
for(j = i + ; j <= n; j++){
double tmp = matrix[j][i] / matrix[i][i];
for(k = i; k <= n + ; k++)
matrix[j][k] -= matrix[i][k] * tmp;
}
}
for(i = n; i >= ; i--){
double tmp = matrix[i][n + ];
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 = ; i <= n; i++) scanf("%lf", &last[i]);
for(int i = ; i <= n; i++){
t = ;
for(int j = ; j <= n; j++){
double tmp; scanf("%lf", &tmp);
matrix[i][j] = * (tmp - last[j]);
t += tmp * tmp - last[j] * last[j];
last[j] = tmp;
}
matrix[i][n + ] = t;
}
gauss();
for(int i = ; i <= n; i++){
if(i < n) printf("%.3lf ", ans[i]);
else printf("%.3lf\n", ans[i]);
}
return ;
}
【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 = ;
double matrix[N][N], ans[N], ret;
int n, m, num, degree[N];
int st[], ed[];
double gg[]; inline void addEdge(const int &u, const int &v){
degree[u]++;
degree[v]++;
st[++num] = u, ed[num] = v;
} inline int read(){
int i = , f = ; char ch = getchar();
for(; (ch < '' || ch > '') && ch != '-'; ch = getchar());
if(ch == '-') f = -, ch = getchar();
for(; ch >= '' && ch <= ''; ch = getchar())
i = (i << ) + (i << ) + (ch -'');
return i * f;
} inline void gauss(){
int i, j, l, k;
for(i = ; i <= n; i++){
l = i;
for(j = i + ; j <= n; j++)
if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;
if(l != i) for(j = i; j <= n + ; j++)
swap(matrix[i][j], matrix[l][j]);
for(j = i + ; j <= n; j++){
double tmp = matrix[j][i] / matrix[i][i];
for(k = i; k <= n + ; k++)
matrix[j][k] -= matrix[i][k] * tmp;
}
}
for(i = n; i >= ; i--){
double tmp = matrix[i][n + ];
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 = ; i <= m; i++){
int u = read(), v = read();
addEdge(u, v);
}
int i, j;
for(i = ; 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 = ; i <= n; i++) matrix[n][i] = ;
for(i = ; i <= n; i++) matrix[i][i] = -1.0;
matrix[][n + ] = -1.0;
gauss();
for(i = ; i <= m; i++)
gg[i] = ans[st[i]] / degree[st[i]] + ans[ed[i]] / degree[ed[i]];
sort(gg + , gg + m + , cmp);
for(i = ; i <= m; i++) ret += gg[i] * i;
printf("%.3f\n", ret);
return ;
}
【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 = , M = ;
int n, m;
int ecnt, st[M << ], ed[M << ], len[M << ], 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 = ; i <= n; i++){
l = i;
for(j = i + ; j <= n; j++)
if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;
if(l != i) for(j = i; j <= n + ; j++)
swap(matrix[i][j], matrix[l][j]);
for(j = i + ; j <= n; j++){
double tmp = matrix[j][i] / matrix[i][i];
for(k = i; k <= n + ; k++)
matrix[j][k] -= matrix[i][k] * tmp;
}
}
for(i = n; i >= ; i--){
double t = matrix[i][n + ];
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 = ; i <= m; i++){
int u, v, w; scanf("%d%d%d", &u, &v, &w);
addEdge(u, v, w);
}
for(i = ; i <= ; i++){
memset(matrix, , sizeof matrix);
memset(ans, , sizeof ans);
for(j = ; j <= n; j++) matrix[j][j] = ;
for(j = ; j <= ecnt; j++){
int l = len[j], u = st[j], v = ed[j];
if(u == n) continue;
if((l >> i) & ){
matrix[u][v] += 1.0 / degree[u];
matrix[u][n + ] += 1.0 / degree[u];
}
else matrix[u][v] -= 1.0 / degree[u];
}
gauss();
ret += ans[] * ( << i);
}
printf("%.3f\n", ret);
return ;
}
【高斯消元】兼 【期望dp】例题的更多相关文章
- 高斯消元与期望DP
高斯消元可以解决一系列DP序混乱的无向图上(期望)DP DP序 DP序是一道DP的所有状态的一个排列,使状态x所需的所有前置状态都位于状态x前: (通俗的说,在一个状态转移方程中‘=’左侧的状态应该在 ...
- LOJ 2542 「PKUWC2018」随机游走 ——树上高斯消元(期望DP)+最值反演+fmt
题目:https://loj.ac/problem/2542 可以最值反演.注意 min 不是独立地算从根走到每个点的最小值,在点集里取 min ,而是整体来看,“从根开始走到点集中的任意一个点就停下 ...
- HDU4870_Rating_双号从零单排_高斯消元求期望
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4870 原题: Rating Time Limit: 10000/5000 MS (Java/Other ...
- hdu 4870 rating(高斯消元求期望)
Rating Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- Luogu3232 HNOI2013 游走 高斯消元、期望、贪心
传送门 这种无向图上从一个点乱走到另一个点的期望题目好几道与高斯消元有关 首先一个显然的贪心:期望经过次数越多,分配到的权值就要越小. 设$du_i$表示$i$的度,$f_i$表示点$i$的期望经过次 ...
- 【BZOJ3143】【HNOI2013】游走 && 【BZOJ3270】博物馆 【高斯消元+概率期望】
刚学完 高斯消元,我们来做几道题吧! T1:[BZOJ3143][HNOI2013]游走 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小 ...
- loj2542 「PKUWC2018」随机游走 MinMax 容斥+树上高斯消元+状压 DP
题目传送门 https://loj.ac/problem/2542 题解 肯定一眼 MinMax 容斥吧. 然后问题就转化为,给定一个集合 \(S\),问期望情况下多少步可以走到 \(S\) 中的点. ...
- 【BZOJ-3143】游走 高斯消元 + 概率期望
3143: [Hnoi2013]游走 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2264 Solved: 987[Submit][Status] ...
- 【BZOJ-3270】博物馆 高斯消元 + 概率期望
3270: 博物馆 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 292 Solved: 158[Submit][Status][Discuss] ...
- [ACM] hdu 4418 Time travel (高斯消元求期望)
Time travel Problem Description Agent K is one of the greatest agents in a secret organization calle ...
随机推荐
- DOM知识梳理
DOM 我们知道,JavaScript是由ECMAScript + DOM + BOM组成的.ECMAScript是JS中的一些语法,而BOM主要是浏览器对象(window)对象的一些相关知识的集合. ...
- 一键帮你复制多个文件到多个机器——PowerShell小脚本(内附PS远程执行命令问题解析)
作为一个后台程序猿,经常需要把一堆程序集(DLL)或者应用程序(EXE)复制到多个服务器上,实现程序的代码逻辑更新,用以测试新的功能或改动逻辑.这里给大家介绍一个自己实现的PowerShell脚本,方 ...
- css如何让div和页面等高?
我们都知道,只要是block状态的标签,宽度和父级等宽,或者设置宽度100%也可以等宽,但设置高度100%是不管用的,那么如何让标签和页面等高呢,除了用js去动态计算设置高度值,用css也可以 只要将 ...
- Asp.Net Core-----简介与安装
Asp.Net Core简介 ASP.NET Core 是一个全新的开源.跨平台框架,可以用它来构建基于网络连接的现代云应用程序,比如:Web 应用,IoT(Internet Of Things,物联 ...
- java音视频编解码问题:16/24/32位位音频byte[]转换为小端序short[],int[],以byte[]转short[]为例
前言:Java默认采用大端序存储方式,实际编码的音频数据是小端序,如果处理单8bit的音频当然不需要做转换,但是如果是16bit或者以上的就需要处理成小端序字节顺序. 注:大.小端序指的是字节的存储顺 ...
- java加密算法入门(二)-对称加密详解
1.简单介绍 什么是对称加密算法? 对称加密算法即,加密和解密使用相同密钥的算法. 优缺点: 优点:算法公开.计算量小.加密速度快.加密效率高. 缺点: (1)交易双方都使用同样钥匙,安全性得不到保证 ...
- 写JS自执行函数时要注意的
JS是非强类型语言,且IDE也不够智能,所以经常会在语句结束时漏写了分号,一般情况下这是不影响运行的, 但如果后面跟上的是一段自执行的函数,就会报出 "..... is not functi ...
- 卷积神经网络的变种: PCANet
前言:昨天和大家聊了聊卷积神经网络,今天给大家带来一篇论文:pca+cnn=pcanet.现在就让我带领大家来了解这篇文章吧. 论文:PCANet:A Simple Deep Learning Bas ...
- Ubuntu安装搜狗拼音和金山快盘
搜狗拼音和金山快盘是UbuntuKylin中的特色中文应用,通过下述方法在Ubuntu或UbuntuKylin中安装. 一.更新Fcitx 1.由于 Ubuntu 12.04自带的 小企鹅输入法Fci ...
- PHPStorm中的快捷键
1.Ctrl+Alt+L 格式化代码 2.windows下按下快捷`Ctrl`+`Shift`+`-`,这样就能折叠所有代码了. 3.windows下按下快捷`Ctrl`+`Shift`+`+`,这样 ...