zoukankan      html  css  js  c++  java
  • HDU 4870 Rating(高斯消元 )

    HDU 4870   Rating

    这是前几天多校的题目,高了好久突然听旁边的大神推出来说是可以用高斯消元,一直喊着赶快敲模板,对于从来没有接触过高斯消元的我来说根本就是一头雾水,无赖之下这几天做DP,正好又做到了这个题,没办法得从头开始看,后来在网上找了别人的高斯消元的模板后发现其实也还是很好理解,就是先构造一个增广矩阵,然后化行阶梯形,最后迭代求解

    首先有一个介绍高斯消元感觉过于详细的博客http://blog.csdn.net/tsaid/article/details/7329301

    首先看一下这个题怎么构造这个增广矩阵,我们把所有可以达到的分数组合作为一个点,再考虑它与其他点所连的边,例如:

    (300, 200)<--(1-p)----(300, 300)-----(p)----->(350, 300)

          a                               b                                    c

    我们就可以理解为有一条b--->a的权值为(1-p)的边,有一条b---->c的权值为p的边,那这样首先构造状态转移方程:

    DP[b] = 1 + (1-p) * DP[a] + p * DP[c]

    变形后得到:

    DP[b] - p * DP[c] - (1-p) * DP[a] = 1;

    这就是我们的增广矩阵的系数了,对于方程的一般形式Ax = B,可以理解为第b个方程中的变元的系数为A[b][b] = 1, A[b][c] = p, A[b][a] = (1-p),B[b] = 1

    这样就构造出了一个(A,B)的一个增广矩阵,保存在a中

    然后就是高斯消元化行阶梯行,看看代码很好理解,就只有两个操作r1<-->r2,交换两行,r2 = r2 - r1 * a   (其中a为一个常系数)

    第一次写Gauss 代码比较戳,可以根据网上详细的介绍结合代码看,很容易懂的

    void gauss()
    {
            int col = 0;
            for(int k=0;k<cnt && col < cnt;k++, col ++)
            {
                        double Max = fabs(a[k][col]);
                        int  Maxr = k;
                        for(int r = k + 1; r < cnt; r ++)
                                if( fabs(a[r][col])  -  Max  >  eps  )
                                        Max  =  fabs( a[Maxr = r][col] );
                        if(fabs(Max) < eps)  {  k --;  continue;  }
                        for(int c = col;c<=cnt; c ++ )
                                SWAP(a[Maxr][c],  a[k][c]  );
                        for(int r = k + 1; r < cnt; r ++ ) if( fabs(a[r][col]) > eps  )
                        {
                                double tmp = a[r][col] / a[k][col];
                                for(int c = col; c <= cnt; c ++ )
                                        a[r][c] -= tmp * a[k][c];
                        }
            }
    }

    化行阶梯行后就是迭代求解了,由于这里一定有解,所以不需要判断无解的情况,直接算就是了

    1        for(int r=cnt-1;r>=0;r--)
    2         {
    3                     for(int c = cnt-1;c>r;c--)
    4                             a[r][cnt] -= a[r][c] * ans[c];
    5                     ans[r] = a[r][cnt] / a[r][r];
    6         }

    最后的总复杂度就是O(n^3)n接近200

    另外还有一个复杂度O(n)的解法的思路(N=20)http://www.cnblogs.com/gj-Acit/p/3888390.html

      1 #include <map>
      2 #include <set>
      3 #include <stack>
      4 #include <queue>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <vector>
      8 #include <cstdio>
      9 #include <cctype>
     10 #include <cstring>
     11 #include <cstdlib>
     12 #include <iostream>
     13 #include <algorithm>
     14 using namespace std;
     15 #define INF ((LL)100000000000000000)
     16 #define inf (-((LL)1<<40))
     17 #define lson k<<1, L, mid
     18 #define rson k<<1|1, mid+1, R
     19 #define mem0(a) memset(a,0,sizeof(a))
     20 #define mem1(a) memset(a,-1,sizeof(a))
     21 #define mem(a, b) memset(a, b, sizeof(a))
     22 #define FOPENIN(IN) freopen(IN, "r", stdin)
     23 #define FOPENOUT(OUT) freopen(OUT, "w", stdout)
     24 template<class T> T CMP_MIN ( T a, T b ) { return a < b;   }
     25 template<class T> T CMP_MAX ( T a, T b ) { return a > b;   }
     26 template<class T> T MAX ( T a, T b ) { return a > b ? a : b; }
     27 template<class T> T MIN ( T a, T b ) { return a < b ? a : b; }
     28 template<class T> T GCD ( T a, T b ) { return b ? GCD ( b, a % b ) : a; }
     29 template<class T> T LCM ( T a, T b ) { return a / GCD ( a, b ) * b;       }
     30 template<class T> void SWAP( T& a, T& b ) { T t = a; a = b;  b = t; }
     31 
     32 //typedef __int64 LL;
     33 typedef long long LL;
     34 const int MAXN = 255;
     35 const int MAXM = 110000;
     36 const double eps = 1e-12;
     37 int dx[4] = { -1, 0, 0, 1};
     38 int dy[4] = {0, -1, 1, 0};
     39 
     40 double p;
     41 int  id[30][30], cnt, N = 20;
     42 double G[400][400], a[300][300], ans[300];
     43 struct NODE
     44 {
     45         int u, d;
     46         NODE(){}
     47         NODE(int _u, int _d):u(_u), d(_d){}
     48 };
     49 
     50 void preInit()
     51 {
     52         cnt = 0;
     53         for(int i=0;i<=N-1;i++)
     54         {
     55                 for(int j = 0; j <= i; j ++ )
     56                 {
     57                         id[i][j] = cnt++;
     58                 }
     59         }
     60         id[N][N-1] = cnt ++;
     61 }
     62 
     63 void init()
     64 {
     65         preInit();
     66         mem0(G);mem0(a);
     67         for(int i=0;i<=N-1;i++)
     68         {
     69                 for(int j=0;j<=i;j++)
     70                 {
     71                         int nx = MAX(i, j + 1), ny = MIN(i, j + 1);
     72                         G[id[i][j]][id[nx][ny]] = p;
     73                         nx = i; ny = (j- 2) >= 0 ? j-2 : 0;
     74                         G[id[i][j]][id[nx][ny]] = 1-p;
     75                 }
     76         }
     77         for ( int i = 0; i < cnt; i++ )
     78         {
     79                 a[i][i] = a[i][cnt] = 1.0;
     80                 if ( i == cnt-1 ) { a[i][cnt] = 0; }
     81                 for ( int j = 0; j < cnt; j++ ) if ( fabs ( G[i][j] ) > eps )
     82                             a[i][j] -= G[i][j];
     83         }
     84 }
     85 
     86 
     87 void gauss()
     88 {
     89         int col = 0;
     90         for(int k=0;k<cnt && col < cnt;k++, col ++)
     91         {
     92                     double Max = fabs(a[k][col]);
     93                     int  Maxr = k;
     94                     for(int r = k + 1; r < cnt; r ++)
     95                             if( fabs(a[r][col])  -  Max  >  eps  )
     96                                     Max  =  fabs( a[Maxr = r][col] );
     97                     if(fabs(Max) < eps)  {  k --;  continue;  }
     98                     for(int c = col;c<=cnt; c ++ )
     99                             SWAP(a[Maxr][c],  a[k][c]  );
    100                     for(int r = k + 1; r < cnt; r ++ ) if( fabs(a[r][col]) > eps  )
    101                     {
    102                             double tmp = a[r][col] / a[k][col];
    103                             for(int c = col; c <= cnt; c ++ )
    104                                     a[r][c] -= tmp * a[k][c];
    105                     }
    106         }
    107         for(int r=cnt-1;r>=0;r--)
    108         {
    109                     for(int c = cnt-1;c>r;c--)
    110                             a[r][cnt] -= a[r][c] * ans[c];
    111                     ans[r] = a[r][cnt] / a[r][r];
    112         }
    113 }
    114 
    115 int main()
    116 {
    117 //        FOPENIN ( "in.txt" );
    118 //       FOPENOUT("out.txt");
    119         while ( ~scanf ( "%lf", &p ) )
    120         {
    121                 init();
    122                gauss();
    123                 printf("%.9lf
    ", ans[0]);
    124         }
    125         return 0;
    126 }
  • 相关阅读:
    iframe高度100%,自适应高度
    怎么让frameset出现整体滚动条
    页面返回顶部
    HTML页面跳转的5种方法
    java web中路径问题。
    sql server数据库添加记录
    如何获取新浪微博背景图
    JavaScript检查是否包含某个字符
    纯JS省市区三级联动
    document.getElementById方法在火狐和谷歌浏览器兼容
  • 原文地址:https://www.cnblogs.com/gj-Acit/p/3888382.html
Copyright © 2011-2022 走看看