【高斯消元】兼 【期望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 ...
随机推荐
- Ajax请求(二)--JQuery的Ajax请求方法
JQuery库的Ajax请求的几种方法: 1. load( url, [data], [callback] ) :载入远程 HTML 文件代码并插入至 DOM 中. 参数含义: url (String ...
- java并发编程(Exchanger)
package org.bianqi.demo1; import java.util.concurrent.Exchanger; import java.util.concurrent.Executo ...
- Docker容器管理平台Humpback进阶-私有仓库
Docker私有仓库 在 Docker 中,当我们执行 docker pull xxx 的时候,可能会比较好奇,docker 会去哪儿查找并下载镜像呢? 它实际上是从 registry.hub.doc ...
- MyBatis7:MyBatis插件及示例----打印每条SQL语句及其执行时间
Plugins 摘一段来自MyBatis官方文档的文字. MyBatis允许你在某一点拦截已映射语句执行的调用.默认情况下,MyBatis允许使用插件来拦截方法调用 Executor(update.q ...
- 开发Activity步骤
第一步:写一个累继承Activity第二步:重写onCreate方法第三步:在主配置文件中注册activity <activity android:name=".类名" an ...
- web存储之webstorage
web存储分类 客户端和服务端 认识web存储 随着web应用的发展,是的客户端存储的用途越来越多,然而实现客户端端存储的方式也是越来越多样化.最简单最兼容的方式就是cookie,但作为真正的客户端存 ...
- ReactiveCocoa源码解析(二) Bag容器的代码实现
今天博客我接着上篇博客的内容来,上篇博客我们详细的看了ReactiveSwift中的Observer已经Event的代码实现.接下来我们来看一下ReactiveSwift中的结构体Bag的实现.Bag ...
- octomap中3d-rrt路径规划
路径规划 碰撞冲突检测 在octomap中制定起止点,目标点,使用rrt规划一条路径出来,没有运动学,动力学的限制,只要能避开障碍物. 效果如下: #include "ros/ros.h&q ...
- 执行3小时超长SQL的分析优化过程:从索引遇见IS NULL,到最佳实践
月底高峰期,对一个典型项目抽查分析时,发现了一个超级慢.全表扫描的SQL,语句很简单,AWR中赫然在列,在我统计的截止时间内还没有结束... 使用v$active_session_history进一步 ...
- ReactiveObjC使用
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #78492a; background-color: #fffff ...