高斯消元

明天就是noip了,写写算法应该能涨rp吧?!
不用矩阵来解释就很好理解了

适用

求解方程组:
a1x1+a2x2+a3x3+...+anxn=val1n;
b1y1+b2y2+b3y3+...+bnyn=val2n;
...;
...........................................=valmn;

算法流程

*让它的系数矩阵变为一个上三角矩阵

  1. 1-n列递推
  2. 找到当前列中(当前该方程的前j-1项均为0)系数最大的,并将系数最大的那一行与当前所在行(第j行)的方程交换,这样方便精度处理?)
  3. 把j+1行至n行的第j个未知数消去
    *由上三角矩阵推得方程解
  4. n-1递推
  5. 当前推到i行,则将1-i-1行之间的j列消去,减去对应值

EX bzoj1778

也是一道不错的概率dp吧
因为若无限延时,炸弹爆炸概率为1
lim=1-(1-p/q)^m=1
所以在i个城市爆炸的概率即为在该城市停留的期望除以在所有城市停留的期望
f[i]表示在该城市停留的期望
f[i]-sigma[ffrd[fr] ]=0;
ps:f[1]=sigma[ffr
d[fr] ]+(1-p/q)(加上本身走到本身不爆炸的期望)

a[j][i]表示第j个方程的第i项(a[j][n+1]为该方程的常数)
高斯消元求解即可

#include<bits/stdc++.h>
using namespace std;
const int N=303;
int n,m,d[N],mp[N][N];
double a[N][N],f[N],p,q;
inline void Gauss(){
	for(int i=1;i<=n;i++){
		int mx=i;
		for(int j=i+1;j<=n;j++)if(a[j][i]>a[mx][i])mx=j;
		if(mx!=i)for(int j=i;j<=n+1;++j)swap(a[mx][j],a[i][j]);
		for(int j=i+1;j<=n;j++){
			double t=a[j][i]/a[i][i];
			for(int k=i;k<=n+1;k++)a[j][k]-=t*a[i][k];
		}
	}
	for(int i=n;i;--i){
		for(int j=n;j>i;--j)
			a[i][n+1]-=f[j]*a[i][j];
		f[i]=a[i][n+1]/a[i][i];
	}
}
int main(){
	scanf("%d%d%lf%lf",&n,&m,&p,&q);
	for(int u,v,i=1;i<=m;++i)scanf("%d%d",&u,&v),mp[u][v]=mp[v][u]=1,++d[u],++d[v];
	for(int i=1;i<=n;i++){
		a[i][i]+=1;
		for(int j=1;j<=n;j++)if(mp[j][i])a[j][i]-=(1-p/q)/d[i];
	}
	a[1][n+1]=1-p/q;
	Gauss();
	double sum=0;
	for(int i=1;i<=n;i++)sum+=f[i];
	for(int i=1;i<=n;i++)printf("%.9lf\n",f[i]/sum);
	return 0;
}
posted @ 2018-11-09 20:48  lnyzo  阅读(88)  评论(0)    收藏  举报