• LightOJ 1151 Snakes and Ladders(概率DP + 高斯消元)


    题意:1~100的格子,有n个传送阵,一个把进入i的人瞬间传送到tp[i](可能传送到前面,也可能是后面),已知传送阵终点不会有另一个传送阵,1和100都不会有传送阵。每次走都需要掷一次骰子(1~6且可能性一样),掷多少走多少,目的地超出100重掷,问你走到100所需掷骰子的期望。

    思路:概率DP肯定的,但是会往前传送就很难直接算。用DP[i]代表从i走到100的期望。

    那么如果i没有传送阵,则有:DP[i] = 1 / 6 * sum(DP[i + j]) + 1,1<= j <= 6,如果超出100则有:DP[i] = 1 / 6 * sum((DP[i + j]) + DP[i] * k),k = min(100 - i,6),1<= j < k

    有传送阵:DP[i] - DP[tp[i]] = 0

    然后根据上式解出这个100元1次方程,用高斯消元

    代码:

    #include<set>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<string>
    #include<cstdio>
    #include<cstring>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    typedef long long ll;
    using namespace std;
    const int maxn = 100 + 10;
    const int MOD = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    const double eps = 1e-9;
    double a[maxn][maxn], x[maxn];
    int equ, var;
    int Gauss(){
        int i, j, k, col, max_r;
        for(k = 0, col = 0; k < equ && col < var; k++, col++){
            max_r = k;
            for(i = k + 1; i < equ; i++)
                if(fabs(a[i][col]) > fabs(a[max_r][col]))
                max_r = i;
            if(fabs(a[max_r][col]) < eps) return 0;
            if(k != max_r){
                for(j = col; j < var; j++)
                    swap(a[k][j], a[max_r][j]);
                swap(x[k], x[max_r]);
            }
            x[k] /= a[k][col];
            for(j = col + 1; j < var; j++) a[k][j] /= a[k][col];
            a[k][col] = 1;
            for(i = 0; i < equ; i++)
            if(i != k){
                x[i] -= x[k] * a[i][col];
                for(j = col + 1; j < var; j++) a[i][j] -= a[k][j] * a[i][col];
                a[i][col] = 0;
            }
        }
        return 1;
    }
    int tp[maxn];
    int main(){
        int t, ca = 1;
        scanf("%d", &t);
        while(t--){
            equ = var = 100;
            int n;
            scanf("%d", &n);
            memset(tp, -1, sizeof(tp));
            memset(a, 0, sizeof(a));
            for(int i = 0; i < n; i++){
                int p;
                scanf("%d", &p);
                --p;
                scanf("%d", &tp[p]);
                --tp[p];
            }
            for(int i = 0; i < 100; i++){
                if(tp[i] == -1){
                    int k = min(99 - i, 6);
                    a[i][i] = 6;
                    for(int j = i + 1; j <= i + k; j++){
                        a[i][j] = -1;
                    }
                    if(k < 6) a[i][i] -= 6 - k;
                    x[i] = 6;
                }
                else{
                    a[i][i] = 1;
                    a[i][tp[i]] = -1;
                    x[i] = 0;
                }
            }
            Gauss();
            printf("Case %d: %.8lf
    ", ca++, x[0]);
        }
        return 0;
    }

     

  • 相关阅读:
    关于用户体验的几张图片
    上下翻滚JS特效代码
    关注程序员健康之——缺失营养时的六种信号
    C#基础知识系列之——for循环
    关于程序中的需求的变化,责任的分配
    Silverlight学习之——Canvas对象
    还是觉得应该动手写点东西....
    怎样理解“道不同,不相为谋”这句话呢。。。
    UML图中最基本的是类图
    .NET中各种数据库连接大全
  • 原文地址:https://www.cnblogs.com/KirinSB/p/10539558.html
Copyright © 2020-2023  润新知