Gift Exchanging - UVa 10417 概率dp

来源:互联网 发布:直播源码下载 编辑:程序博客网 时间:2024/05/21 21:39

题意:给你你的n个小伙伴一人给你带了一种类型的礼物,告诉你各个礼物的数量,和每个小伙伴给哪种礼物的概率,问你选择哪种类型的礼物最有可能是第一个人给的,这个概率是多少。

思路:设A为第一个小伙伴给某种礼物的概率,B为所有人给的礼物恰好是给定的数目的概率P(A|B)=P(AB)/P(B)。B的概率由dp递推得出。最后还得除以这个礼物的数目,再找到最大的这个概率。

AC代码如下:

#include<cstdio>#include<cstring>#include<map>using namespace std;typedef long long ll;double dp[100010],p[13][5],eps=1e-10;ll point[100010],S_num[100010],S_pos,pow13[10];map<ll,int> match;int T,t,n,num[5];int dcmp(double x){    return (x>eps)-(x<-eps);}bool check(ll S,int pos){    ll ret=S%pow13[pos+1]/pow13[pos];    if(ret+1<=num[pos])      return true;    else      return false;}int get(ll S,int ret){    int k=match[S];    if(k>0)      return k;    else    {        match[S]=++S_pos;        point[S_pos]=S;        S_num[S_pos]=ret;        dp[S_pos]=0;        return S_pos;    }}void solve(ll S,int pos){    int i,j,k1,k2,ret;    k1=match[S];    ret=S_num[k1]+1;    k2=get(S+pow13[pos],ret);    dp[k2]+=dp[k1]*p[ret][pos];    //printf("%d %d   %lf %lf %lf\n",k1,k2,dp[k2],dp[k1],p[ret][pos]);}int main(){    int i,j,k,pos;    double A,B,MAXN,p2;    ll MAXS,S;    pow13[0]=1;    for(i=1;i<=6;i++)       pow13[i]=pow13[i-1]*13;    scanf("%d",&T);    for(t=1;t<=T;t++)    {        match.clear();        scanf("%d",&n);        for(i=0;i<5;i++)           scanf("%d",&num[i]);        for(i=0;i<n;i++)           for(j=0;j<5;j++)              scanf("%lf",&p[i][j]);        for(j=0;j<5;j++)           p[n][j]=p[0][j];        point[1]=0;        S_num[1]=0;        S_pos=1;        match[0]=1;        dp[1]=1;        //printf("%.3f\n",dp[1]);        for(i=1;i<=S_pos;i++)           for(j=0;j<5;j++)             if(check(point[i],j))               solve(point[i],j);        for(i=1;i<=S_pos;i++)        {            //printf("%d  %lld %lld %.3f\n",i,point[i],S_num[i],dp[i]);        }        B=dp[S_pos];        MAXN=0;        MAXS=0;        for(i=0;i<=4;i++)           MAXS+=pow13[i]*num[i];        for(i=0;i<=4;i++)           if(num[i]>0)           {               S=MAXS-pow13[i];               k=match[S];               p2=p[0][i]*dp[k]/B/num[i];               if(dcmp(p2-MAXN)>0)               {                   MAXN=p2;                   pos=i;               }           }        printf("%d %.3f\n",pos+1,MAXN);    }}




0 0