hdu4870(高斯消元解概率DP)

来源:互联网 发布:李德仁 知乎 编辑:程序博客网 时间:2024/05/21 01:32

这题真的是太为难我了,在接触这题之前,没学过概率dp,没学过高斯消元,为了这道题目,我特地去看了那两个算法,然后才回过来做这题

题意:有两个账号,没次去分数低的去参加比赛,赢的概率是P,赢了之后加1(这里以50为一个单位),输的概率是(1-P),输了之后减2

思路:设 x , y 是当前两个分数,那么状态转移为f ( x , y )  = 1 + p( x1 , y1 ) + (1 - p)(x2 , y2),经分析得有210个状态,分别为f(0, 0......19)、f(1, 1......19)......、f(19,19)

然后设用未知数x,x1,x2........x210代替它们,得到210个未知数,然后利用状态转移构造210个方程,最后用guass消元解就可以了

为什么用guass消元解,而不用递推解?因为状态转移方程有后效行,用递推解可以, 但是很难推

代码如下:

#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#include<time.h>#include<math.h>#define N 300#define inf 0x7ffffff#define eps 1e-9#define pi acos(-1.0)#define P system("pause")using namespace std;double p;double A[N][N];int c[30][30];int tot = 0;void init() {        memset(c, -1 ,sizeof(c));//??? 为什么一定要初始化为-1        for (int i = 0; i < 20; ++i) {                for (int j = 0; j <= i; ++j) {                        c[i][j] = tot++;                }        }        //printf("len = %d\n", len);}void get_A()//求系数矩阵A{    memset(A,0,sizeof(A));    int i,j;    int u,v;    for(i = 0; i <= 19; i++)    {        for(j = 0; j < i; j++)        {            u = c[i][j];            A[u][tot] = 1;            A[u][u] = 1;            v = c[i][max(0,j-2)];            A[u][v] -= (1.0-p);            v = c[i][j+1];            A[u][v] -= p;        }        u = c[i][i];        A[u][tot] = 1;        A[u][u] = 1;        v = c[i][max(0,j-2)];        A[u][v] -= 1-p;        v = c[i+1][i];        A[u][v] -= p;    }}void gauss_elimination(int n) //高斯消元解方程组{    int i,j,k,r;    for(i = 0; i < n; i++)    {        r = i;        for(j = i+1; j < n; j++)            if( fabs(A[j][i]) > fabs(A[r][i]) )                r = j;        if(r != i)            for(j = 0; j <= n; j++)                swap(A[r][j],A[i][j]);        for(j = n; j >= i; j--)            for(k = i+1; k < n; k++)                A[k][j] -= A[k][i]/A[i][i]*A[i][j];    }    for(i = n-1; i >= 0; i--)    {        for(j = i+1; j < n; j++)            A[i][n] -= A[j][n]*A[i][j];        A[i][n] /= A[i][i];    }}int main(){    ios::sync_with_stdio(false);//freopen("input.txt","r",stdin);//freopen("output.txt","w",stdout);    init();    while(cin>>p)    {        get_A();        gauss_elimination(210);        printf("%.6lf\n",A[0][210]);    }    return 0;}


0 0
原创粉丝点击