hdu4780 高斯消元 及 非高斯消元

来源:互联网 发布:万网域名登录 编辑:程序博客网 时间:2024/06/12 20:12
#include <cstdio>#include <cstring>#include <cmath>const double eps=1e-7;double dp[20];double p;int main() {    int i,j;    double ans;    while (scanf("%lf",&p)!=EOF) {        dp[0]=1/p;        dp[1]=(1+(1-p)*dp[0])/p;        for (i=2;i<20;i++) {            dp[i]=(1+(1-p)*(dp[i-2]+dp[i-1]))/p;        }        ans=dp[19];        for (i=0;i<19;i++) {            ans+=dp[i]+dp[i];        }        printf("%.8lf\n",ans);    }    return 0;}

先贴代码。。。高斯消元,dp[i][j]代表i>=j时候距离目标期望多少步。。然后。。。发现是个等式。。。解方程
dp[i][j] = p*(dp[i][j+1])+(1-p)*(dp[i][j-2])+1
当i == j 时候注意变i
高斯消元
其实还有更机智的做法
dp[i]表示第i分到第i+1分 的期望 dp[i]=1+p*0+(1-p)*(dp[i-2]+dp[i-1]+dp[i])

然后变换一下式子直接转移就行。。。O(20)复杂度

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>using namespace std;const double eps = 1e-9;const int N = 305;double p , a[N][N];int mark[25][25];double solve() {    for (int i = 0; i < 210; i ++) {    int k = i;    for (; k < 210; k++)        if (fabs(a[k][i]) > eps) break;    for (int j = 0; j <= 210; j++)       swap(a[i][j], a[k][j]);    for (int j = 0; j < 210; j++) {        if (i == j) continue;        if (fabs(a[j][i]) > eps) {        double x = a[j][i] / a[i][i];        for (int k = i; k <= 210; k++) {            a[j][k] -= a[i][k] * x;        }        }    }    }    return a[0][210] / a[0][0];}void build(){memset( a , 0 , sizeof ( a ) );for (int i = 0 ; i < 20 ; i ++){for (int j = 0 ; j < i ; j ++){int u =  mark[i][j];a[u][u] = 1;a[u][210] = 1;int v = mark[i][max(0,j-2)];a[u][v] -= ( 1 - p );v = mark[i][j+1];a[u][v] -= p;}int u = mark[i][i];a[u][u]=1;a[u][210] = 1;int v = mark[i][max(0,i-2)];a[u][v] -= (1-p);v = mark[i+1][i];a[u][v] -= p;}}int main(){int cnt = 0 ; memset( mark , -1 , sizeof ( mark ) );for ( int i = 0 ; i < 20 ; i ++ ){for ( int j = 0 ; j <= i ; j ++ ){mark[i][j] = cnt++;}}while ( scanf("%lf" , &p) != EOF ){build();printf("%.6lf\n" , solve());}return 0;}


0 0
原创粉丝点击