• uva 11181 Probability|Given


    数学题(概率基础题+暴力)

    题意:给你n个人,给出每个人会购物的概率,然后给你r,即r个人会购物其余人都不购物。然后需要你输出n行,第i行就是这个r个人中有一个是第i个的概率是多少

    其原型就是,有5个人,选3个人出来,甲在其中的概率。不过5变成了n,3变成了r。这个样子的话就是一个条件概率

    即pb为从n个人中选r个的概率。pa就是甲在其中的概率   pa/pb就是答案

    这个样的话,只能暴力了(我只能想到暴力),即在n个人中找出r个人(就是一个组合,不是排列),把这r个人的概率相乘其余人的反面概率相乘。然后所有的这些我概率相加就是pb。然后同样的,选定甲,再选r-1个人(组合),甲和这r-1个人的概率相乘,其余人的反概率相乘,然后相加就是pa

    这两个过程是可以合并在一起的

    然后主要说一下怎么构建组合,我用的方法是递归构建,而且是增序构建,这样才能区别组合和排列

    好像123是一个组合,123,132,312,231…………这些是排序,不能算进去会重复,所以就要求增序,显然123只有123这种唯一情况

    然后就看代码吧,怎么把算pa和pb的过程合并,看了代码应该都会明白了

    #include <cstdio>
    #include <cstring>
    #define N 25
    double p[N],ans[N],pb,pa;
    int a[N],n,r,tot;
    
    void add()
    {
        int vis[N];
        double tmp=1;
        //printf("第%d次枚举\n",++tot);
        //for(int i=1; i<=r; i++) 
            //printf("%d ",a[i]); 
        //printf("\n");
    
        memset(vis,0,sizeof(vis));
        for(int i=1; i<=r; i++)
        {
            vis[a[i]]=1;  //标记
            tmp*=p[a[i]];
        }
        for(int i=1; i<=n; i++) 
            if(!vis[i])
                tmp*=(1-p[i]);
        //printf("tmp=%.6f\n",tmp);
    
        for(int i=1; i<=r; i++)
            ans[a[i]]+=tmp;
    
        pb+=tmp;
    }
    void dfs(int c , int pre)  //c是还要再找c个人,pre是前面人的编号
    {
        if(c<=0)  //找完r个人
        {
            add();
            return ;
        }
        for(int i=pre+1; i<=n-c+1; i++) //当前可能枚举的人
        {
            a[r-c+1]=i;
            dfs(c-1,i);
        }
        return ;
    }
    void get_pb_pa()
    {
        /*
        先用递归枚举r个不同的买东西的人,用增序枚举就不会重复,把r个人编号保存下来
        每次递归到第r层也就是枚举结束了,就进去一个处理函数
        处理函数把这r个人的概率相乘,再和其余人的反概率相乘
        只要枚举完所有可能的r个人,那么就得到了pb也就是“只有r个人购物的概率”
        */
        pb=0; 
        tot=0;  //tot只是个用于测试的变量
        dfs(r,0);
        //printf("pb=%.6f\n",pb);
    }
    int main()
    {
        int Case=0;
        while(scanf("%d%d",&n,&r)!=EOF)
        {
            if(!n && !r) break;
            for(int i=1; i<=n; i++) scanf("%lf",&p[i]);
            memset(ans,0,sizeof(ans));
            get_pb_pa();  //单独一个函数计算pb和所有的pa
            printf("Case %d:\n",++Case);
            for(int i=1; i<=n; i++)
                printf("%.6f\n",ans[i]/pb);
            
        }
        return 0;
    }
  • 相关阅读:
    URL收藏
    web网站防攻击策略
    网络编程
    Tomcat
    UML学习
    大数据学习
    PHP学习
    SYNC CSDN
    在浏览器中打开本地程序
    内存管理工具,帮助检查内存泄露及野指针问题
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2831647.html
Copyright © 2020-2023  润新知