HDU4815Little Tiger vs. Deep Monkey(01背包)

题意:

给出N道题,和一个概率P,然后给出每道题对应的得分x(每道题只有两个选项,一个正确一个错误)。两个人来答题,一个人是随机选择答案,问另一个人至少要答多少分才能保证有P的概率不会失败。


思路:

01背包,最大分数为40000,01背包处理,记录这40000个分数出现的次数然后从小分数遍历一边即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 40005;
ll dp[maxn], v[45];
int main()
{
    ll t, n;
    double p;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%I64d%lf", &n, &p);
        memset(dp, 0, sizeof(dp));
        ll sum = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%I64d", &v[i]);
            sum += v[i];
        }
        dp[0] = 1;
        for(int i = 1; i <= n; i++)
            for(int j = sum; j >= v[i]; j--)
                dp[j] += dp[j-v[i]];
        ll tmp = 1LL << n;
        sum = 0;
        for(int i = 0; i <= 40000; i++)
        {
            sum += dp[i];
            if(sum*1.0/tmp >= p)
            {
                printf("%d\n", i);
                break;
            }
        }
    }
    return 0;
}

概率DP写法:


d[i][j],表示前i道题,得分为j的概率 。 这样,最终打完所有题目之后猴子得任意分数的概率我们就知道了,老虎要想赢就要至少

得和他一样的分数,那么就很好办了,从0~max分,不断相加概率,当概率大于P时的分数就是答案

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 50;
const double INF = 10000000.0;
int T,n,a[maxn];
double p,d[50][40000+100];
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%lf",&n,&p);
        ll sum = 0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            sum += a[i];
        }
        memset(d,0,sizeof(d));
        d[0][0] = 1.0;

        for(int i=1; i<=n; i++)
        {
            for(int j=0; j<=sum; j++)
            {
                if(j >= a[i]) d[i][j] += d[i-1][j-a[i]]/2;

                d[i][j] += d[i-1][j]/2;
            }
        }
        int ans;
        double pp = 0.0;
        for(int i=0; i<=sum; i++)
        {
            pp += d[n][i];
            if(pp > p || fabs(pp-p) < 1e-6)
            {
                ans = i ;
                break;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值