2019牛客暑期多校训练营(第十场)A Blackjack —— 概率DP+逆背包,求n个数取一些使得和落在区间a-b范围的概率

202 篇文章 6 订阅

This way

题意:

给你n个数,你每次会取一张牌,你可以随时结束游戏,问你最终你手上牌的值的和落在a+1到b这个区间内的概率是多少

题解:

我看了题解和一些人的代码,说实话我一开始是很蒙逼的
为什么这里要乘这个,为什么这里要除这个,搞了一段时间才懂。
思路是枚举每一张牌作为最后一张符合要求的牌的时候的概率。
我们要处理出 a + 1 − x [ i ] a+1-x[i] a+1x[i] b − x [ i ] b-x[i] bx[i]区间的所有可行解,那么就用背包来求。
我们设dp[f][i][j]表示在当前状态为f(0|1,这是滚动数组)的时候,取j张牌使得和为k的时候的概率。
那么背包就是

dp[i&1][j][k]+=1.0*dp[(i&1)^1][j-1][k-v[i]]*j/(n-j+1);

为什么要*j,因为我们已知当前有j张牌,取出一张变成j-1张牌的情况数有j种。
对于这张牌,有 1 n − j + 1 \frac{1}{n-j+1} nj+11的概率被取出。
首先如果每一次都做一遍背包的话,会T,这时候需要用到逆背包的知识,什么是逆背包,就是将这个数从前往后做,将这个数的影响去掉的操作,至于加回来的时候是从后往前加回来。
为什么从前往后去掉影响。
假设我们现在有一个值得影响为1,背包是
1 2 3 4 5
那么我们要去掉影响的时候,应当从前往后减
1 1 2 2 3
那么我们从后往前背包的话,答案就变回
1 2 3 4 5
了。
dp的时候/n-j的意义与上面相同,也就是从n-j个牌中选出一张的概率。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=505;
int v[N];
double dp[2][N][N];
int main()
{
    int n,a,b;
    scanf("%d%d%d",&n,&a,&b);
    dp[0][0][0]=1;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&v[i]);
        for(int j=0;j<=i;j++)
            for(int k=0;k<=b;k++)
                dp[i&1][j][k]=dp[(i&1)^1][j][k];
        for(int j=1;j<=i;j++)
            for(int k=v[i];k<=b;k++)
                dp[i&1][j][k]+=1.0*dp[(i&1)^1][j-1][k-v[i]]*j/(n-j+1);
    }
    double ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            for(int k=v[i];k<=b;k++)
                dp[n&1][j][k]-=1.0*dp[n&1][j-1][k-v[i]]*j/(n-j+1);
        for(int j=0;j<n;j++)
            for(int k=max(0,a+1-v[i]);k<=min(a,b-v[i]);k++)
                ans+=1.0*dp[n&1][j][k]/(n-j);
        for(int j=n;j>=1;j--)
            for(int k=v[i];k<=b;k++)
                dp[n&1][j][k]+=1.0*dp[n&1][j-1][k-v[i]]*j/(n-j+1);
    }
    printf("%.15f\n",ans);
    return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值