【高斯消元】兼 【期望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 ...
随机推荐
- 浅谈如何保证discuz插件安全
1.非直接执行程序请加上 if(!defined('IN_DISCUZ')) { exit('Access Denied'); } 2.记得过滤 比如说uid等id需要intval过滤,避免溢出 ...
- 利用document的readyState去实现页面加载中的效果
打开新的网页时,为了增强友好性体验,告知用户网页正在加载数据需要呈现一个"页面加载中"之类的提示,只需要利用document就可以实现. 实现示例代码如下: <style&g ...
- R语言统计分析技术研究——岭回归技术的原理和应用
岭回归技术的原理和应用 作者马文敏 岭回归分析是一种专用于共线性分析的有偏估计回归方法,实质上是一种改良的最小二乘估计法,通过放弃最小二乘法的无偏性,以损失部分信息,降低精度为代价获得回归系数更为符合 ...
- ecshop开发帮助
http://www.ecshop.com/template_tutorial/ ECSHOP模板结构说明 http://help.ecshop.com/index.php ECSHOP帮助中心 ht ...
- 委托(C#)
委托,delegate 关键字用于声明一个引用类型,该引用类型可用于封装命名方法或匿名方法.委托类似于 C++ 中的函数指针:但是,委托是类型安全和可靠的.委托类型声明的格式如下: public de ...
- 几种 vue的数据交互形式
var that=this get请求 that.$http.get("1.txt").then(function(result){ console.log(result) thi ...
- Spring Security 概念基础 验证流程
Spring Security 概念基础 验证流程 认证&授权 认证:确定是否为合法用户 授权:分配角色权限(分配角色,分配资源) 认证管理器(Authentication Manager) ...
- [图形学] 结束 [Unity Shader] 开始
历时4个月,终于把<计算机图形学 with OpenGL>啃完了.如果边上班边看,即使一年应该都看不完. 虽然书里用到的GLUT库应该已经废弃,但并不影响用它去理解图形学的内容,我只把它当 ...
- Linux安装SVN服务器
“svn都快淘汰了” #安装subversion yum -y install subversion #创建svn仓库基础路径 mkdir /home/svn #创建svn仓库 svnadmin cr ...
- VB6之CRC32
翻译篇:http://www.cnblogs.com/duzouzhe/archive/2009/08/05/1539543.html Private Declare Function GetTick ...