zoukankan      html  css  js  c++  java
  • HDU 4418 Time travel 期望dp+dfs+高斯消元

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=4418

    Time travel

    Time Limit: 2000/1000 MS (Java/Others)
    Memory Limit: 32768/32768 K (Java/Others)
    #### 问题描述 > Agent K is one of the greatest agents in a secret organization called Men in Black. Once he needs to finish a mission by traveling through time with the Time machine. The Time machine can take agent K to some point (0 to n-1) on the timeline and when he gets to the end of the time line he will come back (For example, there are 4 time points, agent K will go in this way 0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 2, 1, ...). But when agent K gets into the Time machine he finds it has broken, which make the Time machine can't stop (Damn it!). Fortunately, the time machine may get recovery and stop for a few minutes when agent K arrives at a time point, if the time point he just arrive is his destination, he'll go and finish his mission, or the Time machine will break again. The Time machine has probability Pk% to recover after passing k time points and k can be no more than M. We guarantee the sum of Pk is 100 (Sum(Pk) (1 <= k <= M)==100). Now we know agent K will appear at the point X(D is the direction of the Time machine: 0 represents going from the start of the timeline to the end, on the contrary 1 represents going from the end. If x is the start or the end point of the time line D will be -1. Agent K want to know the expectation of the amount of the time point he need to pass before he arrive at the point Y to finish his mission. > If finishing his mission is impossible output "Impossible !" (no quotes )instead.

    输入

    There is an integer T (T <= 20) indicating the cases you have to solve. The first line of each test case are five integers N, M, Y, X .D (0< N,M <= 100, 0 <=X ,Y < 100 ). The following M non-negative integers represent Pk in percentile.

    输出

    For each possible scenario, output a floating number with 2 digits after decimal point
    If finishing his mission is impossible output one line "Impossible !"
    (no quotes )instead.

    样例输入

    2
    4 2 0 1 0
    50 50
    4 1 0 2 1
    100

    样例输出

    8.14
    2.00

    题意

    一个人坐时光机,在时间轴上(0~n-1)来回运动,这个人向前运动k步的概率为p[k](k>=1&&k<=m),现在他要从X到Y,给你初始的X和初始运动方向,以及终点Y,问你他到终点时的期望步数。

    题解

    典型的dfs+高斯消元
    首先我们可以把来回走拆成一条直线,如 0 1 2 可以拆成 0 1 2 1。这样就可以循环处理了。
    然后dp[i]表示从i点到终点的期望步数,则有dp[i]=sigma(pro[x]*(dp[i+x]+x)),既sigma(pro[x]*dp[i+x])-dp[i]=-sigma(pro[x]*x)。列(n-1)*2个方程(只对那些起点可达的列方程),高斯求一下解就可以了。

    代码

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=0x3f3f3f3f3f3f3f3fLL;
    const double eps=1e-9;
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    const int maxn=233;
    
    typedef double Matrix[maxn][maxn];
    
    ///n*(n+1)的增广矩阵
    bool gauss_jordan(Matrix A,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(fabs(A[r][i])<eps) continue;
            if(r!=i) for(j=0; j<=n; j++) swap(A[r][j],A[i][j]);
    
            for(k=0; k<n; k++) if(k!=i) {
                for(j=n; j>=i; j--) A[k][j]-=A[k][i]/A[i][i]*A[i][j];
            }
        }
    
        ///矛盾式
        for(int i=n-1; i>=0&&fabs(A[i][i])<eps; i--) {
            if(fabs(A[i][n])>eps) return false;
        }
        return true;
    }
    
    Matrix A;
    
    int n,m,Y,X,D;
    int arr[maxn];
    double pro[maxn];
    
    int tot;
    void get_arr(){
        tot=0;
        if(X==0){
            for(int i=0;i<n;i++) arr[tot++]=i;
            for(int i=n-2;i>0;i--) arr[tot++]=i;
        }else if(X==n-1){
            for(int i=n-1;i>=0;i--) arr[tot++]=i;
            for(int i=1;i<n-1;i++) arr[tot++]=i;
        }else if(D==0){
            for(int i=X;i<n;i++) arr[tot++]=i;
            for(int i=n-2;i>=0;i--) arr[tot++]=i;
            for(int i=1;i<X;i++) arr[tot++]=i;
        }else{
            for(int i=X;i>=0;i--) arr[tot++]=i;
            for(int i=1;i<n;i++) arr[tot++]=i;
            for(int i=n-2;i>X;i--) arr[tot++]=i;
        }
    }
    
    int vis[maxn];
    bool flag=0;
    void dfs(int u){
        vis[u]=1;
        if(arr[u]==Y) flag=true;
        for(int i=1;i<=m;i++){
            if(fabs(pro[i])<eps) continue;
            int des=(u+i)%tot;
            if(vis[des]) continue;
            dfs(des);
        }
    }
    
    void init(){
        clr(A,0);
        clr(vis,0);
    }
    
    int main() {
        int tc;
        scf("%d",&tc);
        while(tc--){
            scf("%d%d%d%d%d",&n,&m,&Y,&X,&D);
             for(int i=1;i<=m;i++){
                scf("%lf",&pro[i]); pro[i]/=100;
            }
            init();
            get_arr();
    
            flag=false;
            dfs(0);
            if(!flag){
                prf("Impossible !
    ");
                continue;
            }
    
            for(int i=0;i<tot;i++){
                if(!vis[i]) continue;
                if(arr[i]==Y){
                    A[i][i]=1.0;
                    continue;
                }
                A[i][i]=-1.0,A[i][tot]=0;
                for(int j=1;j<=m;j++){
                    int des=(i+j)%tot;
                    A[i][des]+=pro[j];
                    A[i][tot]-=pro[j]*j;
                }
            }
    
            bool su=gauss_jordan(A,tot);
    
            if(!su||fabs(A[0][0])<eps) prf("Impossible !
    ");
            else prf("%.2lf
    ",A[0][tot]/A[0][0]);
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
  • 相关阅读:
    Java 多个线程之间共享数据
    Mysql索引为什么要采用B+Tree而非B-Tree
    MyBatis常见面试题:通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
    CentOS 8.1 基于二进制安装docker
    shell实现一键证书申请和颁发脚本
    配置DNS的主从以及实现域名反向解析
    利用Dockerfile实现nginx的部署
    编译安装Mariadb-10.5.5
    登录mysql出错:mysql: error while loading shared libraries: libtinfo.so.5: cannot open share
    一键安装MySQL5.7脚本
  • 原文地址:https://www.cnblogs.com/fenice/p/5973060.html
Copyright © 2011-2022 走看看