hdu4815- Little Tiger vs. Deep Monkey-概率dp或者背包计数

背包计数真神奇。
概率dp也神奇。
https://cn.vjudge.net/contest/157865#problem/C
简明说一下题意,有一个机器变态人,大概和汉芯一样,是个骗人的玩意,
出了n个问题,变态人其实只能随机的选择答案,得到的分数是未知的。
给定一个概率,小老虎想确保这个赢他的概率。
问你最少需要答对多少题。
那么重点便在于对题意的理解了。
只要x/y>=p,x为小老虎大于机器人的频数,y代表小老虎的所有频数。
y为2的n次方,x自己累加就行。
卡的地方:1<<42错了,,太大了,改成pow就对了,。
或者用1ll<<42,在位移之前就将其改变成long long了
(普通的转化也不行哦。)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
/* 这个概率dp的做法


*/
double dp[50][44001];
int a[50],b[50];
int main()
{
   int x,y,t;
   double h;
   cin>>t;
   while(t--)
   {
     cin>>x>>h;
     int sum=0;
     for(int i=1;i<=x;i++)
     {
         scanf("%d",&a[i]);
         sum+=a[i];
         b[i]=sum;
     }
     memset(dp,0,sizeof(dp));
      dp[0][0]=1;
       for(int i=1;i<=x;i++)
            for(int  j=0;j<=sum;j++)
           {    if(a[i]<=j)
                dp[i][j]=(dp[i-1][j]+dp[i-1][j-a[i]])*0.5;//上一次是这个份的1/2加上 上一次比这个份低了的1/2;
                else
                    dp[i][j]=dp[i-1][j]*0.5;//上一次是这个分的二分之1,(剩下1/2也可能是被人家抢走了);
           }
      double g=0;
      }
      for(int i=0;i<=sum;i++)
      {
         g+=dp[x][i];
         if(g>=h)
         {
             printf("%d\n",i);
             break;
         }
      }
   }
   return 0;
}

01背包

#include <bits/stdc++.h>
const int maxn=440005;
using namespace std;
int main()
{    int t;
    int m;
    double p;
    int a[60];
    int dp[maxn];
    int  sum=0;
     scanf("%d",&t);
     while(t--)
     {   sum=0;
         scanf("%d%lf",&m,&p);
          for(int i=0;i<m;i++)
          {  scanf("%d",&a[i]);
              sum+=a[i];
          }
          memset(dp,0,sizeof(dp));
          dp[0]=1;
         for(int i=0;i<m;i++)
            for(int   j=sum;j>=a[i];j--)
              dp[j]+=dp[j-a[i]];
         //long long tim=ceil(pow(2,m)*p);
         long long tim=ceil((1ll<<m)*p);
         //cout<<tim<<endl;
         //for(int i=0;i<sum;i++)
           // printf("%d ",dp[i]);
         long long num=0;
         for(int i=0;i<=sum;i++)
         {   num+=dp[i];
              if(num>=tim)
              {   printf("%d\n",i);
                  break;
              }

         }
     // printf("e");
     }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值