bzoj 3029 守卫者的挑战——概率期望dp+状态数思考

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3029

先随便写了个dfs,记录“前 i 次、成功 j 次、容量-残片=k”的概率。因为是否可行只和“成功次数”还有“容量-残片个数”有关,和容量、残片具体数量无关。准备记忆化,但发现状态存不下。

#include<iostream>
#include<cstdio>
#include<cstring>
#define db double
using namespace std;
const int N=205,M=202005;
int n,l,K,a[N];
db p[N],ans;
void dfs(int i,int j,int c,double w)//至少有c个
{
    if(c>n)c=n;
    if(i>n)
    {
        if(j>=l&&c>=0)ans+=w;return;
    }
    if(j+(n-i+1)<l)return;
    if(a[i]>=0)
    {
        dfs(i+1,j+1,c+a[i],w*p[i]);
        dfs(i+1,j,c,w*(1-p[i]));
    }
    else
    {
        dfs(i+1,j+1,c-1,w*p[i]);
        dfs(i+1,j,c,w*(1-p[i]));
    }
}
int main()
{
    scanf("%d%d%d",&n,&l,&K);int x;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);p[i]=(db)x/100;
    }
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    dfs(1,0,K,1);
    printf("%.6lf\n",ans);
    return 0;
}

然后想到了 bzoj4247 挂饰 的思路。就是发现“容量-残片数量”大于n的话多出来的部分没什么用,可以把大于n记成等于n。这样第三维就只有2*n啦!然后就可以刷表了。

#include<iostream>
#include<cstdio>
#include<cstring>
#define db double
using namespace std;
const int N=205,M=202005;
int n,l,K,a[N];
db p[N],ans,dp[2][N][N<<1];
int main()
{
    scanf("%d%d%d",&n,&l,&K);int x;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);p[i]=(db)x/100;
    }
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    dp[0][0][min(n,K)+N]=1;
    for(int i=0;i<n;i++)
    {
        int d=(i&1);
        for(int j=0;j<i;j++)
            for(int k=-n;k<=n;k++)dp[!d][j][k+N]=0;
        for(int j=0;j<=i;j++)
            for(int k=-n;k<=n;k++)
            {
                if(a[i+1]>=0)
                {
                    dp[!d][j+1][min(n,k+a[i+1])+N]+=dp[d][j][k+N]*p[i+1];//+=
                    dp[!d][j][k+N]+=dp[d][j][k+N]*(1-p[i+1]);
                }
                else
                {
                    dp[!d][j+1][k-1+N]+=dp[d][j][k+N]*p[i+1];
                    dp[!d][j][k+N]+=dp[d][j][k+N]*(1-p[i+1]);
                }
            }
    }
    int d=(n&1);
    for(int j=l;j<=n;j++)
        for(int k=0;k<=n;k++)
            ans+=dp[d][j][k+N];
    printf("%.6lf\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/Narh/p/9362911.html

时间: 2024-10-09 11:30:09

bzoj 3029 守卫者的挑战——概率期望dp+状态数思考的相关文章

BZOJ 3029 守卫者的挑战 期望DP

题目大意:给定n个事件,第i个事件发生的概率为pi,收益为ai,初始收益为k,求n个事件之后发生的事件数>=l且收益>=0的概率 令f[i][j][k]表示第i个事件进行后已经发生了j个事件且当前受益为k的概率 MB破输入法打两行字错了十多遍 第三维好大- - 不会爆? 实际上第三维大于n就没有意义了 因为收益大于n时一定不会扣到负数 因此将第三维大于n的状态全都存到n上即可 时间复杂度O(n^3) 卡内存差评 #include <cstdio> #include <cstr

bzoj 3029: 守卫者的挑战【概率dp】

以后写dp还是向后转移吧--写的把前面加起来的版本怎么也调不过去 首先注意,因为地图碎片只占1体积,所以>n,<-n的体积是没用的,所以就可以把体积降到n级别,然后用这场胜负像后转移即可,滚动数组优化 #include<iostream> #include<cstdio> using namespace std; const int N=405; int n,l,m,a[N]; double p[N],f[2][N][N],ans; int main() { scanf

BZOJ 3029 守卫者的挑战

一开始搞了两个dp数组,分别记到第i盘,胜j盘,拿到k个碎片和背包大小>=k的概率,然后寻思着把它们乘起来? 后来发现好像是错的....这个地方不能用乘法,这两件事情是相关的.(我瞎jb猜的...其实是样例没过) 然后发现只要一个数组就行了....收益就是+a[i],-1,问最后收益>=0,胜场>=l的方案数...然后直接dp. 卡内存差评. #include<iostream> #include<cstdio> #include<cstring> #

【BZOJ-1419】Red is good 概率期望DP

1419: Red is good Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 660  Solved: 257[Submit][Status][Discuss] Description 桌面上有R张红牌和B张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付出1美元.可以随时停止翻牌,在最优策略下平均能得到多少钱. Input 一行输入两个数R,B,其值在0到5000之间 Output 在最优策略下平均能得到多少钱

CF148D--Bag of mice+概率期望dp

第一道概率期望dp:) 其实和一般的dp也差不多,只要状态选好就行了. 定义dp[i][j]表示还剩i只白老鼠j只黑老鼠时候公主赢得概率. 则:1.公主选白老鼠,直接赢,概率:i/(i+j) 2.公主选黑老鼠 1)龙选黑老鼠,逃走黑老鼠:概率:j/(i+j)*(j-1)/(i+j-1)*(j-2)/(i+j-2) 2)  龙选黑老鼠,逃走白老鼠:概率:j/(i+j)*(j-1)/(i+j-1)*i/(i+j-2) 3) 龙选白老鼠,这样公主是必输的,不用考虑 然后dp[i][j]等于以上概率之和

Codeforces - 1264C - Beautiful Mirrors with queries - 概率期望dp

一道挺难的概率期望dp,花了很长时间才学会div2的E怎么做,但这道题是另一种设法. https://codeforces.com/contest/1264/problem/C 要设为 \(dp_i\) 表示第 \(i\) 个格子期望经过多少次,所以 \(dp_{n+1}=1\). https://www.cnblogs.com/suncongbo/p/11996219.html 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12063633.ht

HDU 4336 Card Collector (期望DP+状态压缩 或者 状态压缩+容斥)

题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率,每包至多一张卡片,可能没有卡片.求需要买多少包才能拿到所以的N张卡片,求次数的期望. 析:期望DP,是很容易看出来的,然后由于得到每张卡片的状态不知道,所以用状态压缩,dp[i] 表示这个状态时,要全部收齐卡片的期望. 由于有可能是什么也没有,所以我们要特殊判断一下.然后就和剩下的就简单了. 另一个方法就是状态压缩+容斥,同样每个状态表示收集的状态,由于每张卡都是独立,所以,每个卡片的期望就是1.0/p,然后要做的就是要去重,既然

【TYVJ1864】[Poetize I]守卫者的挑战 概率与期望

[TYVJ1864][Poetize I]守卫者的挑战 描述 打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜寻着关押applepi的监狱的所在地.突然,眼前一道亮光闪过."我,Nizem,是黑魔法圣殿的守卫者.如果你能通过我的挑战,那么你可以带走黑魔法圣殿的地图--"瞬间,队员们被传送到了一个擂台上,最初身边有一个容量为K的包包. 擂台赛一共有N项挑战,各项挑战依次进行.第i项挑战有一个属性ai,如果ai>=0,表示这次挑战成功后可以再获得一个容量为ai的包包:如

TYVJ.1864.[Poetize I]守卫者的挑战(概率DP)

题目链接...无 题目: P1864 [Poetize I]守卫者的挑战 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜寻着关押applepi的监狱的所在地.突然,眼前一道亮光闪过. "我,Nizem,是黑魔法圣殿的守卫者.如果你能通过我的挑战,那么你可以带走黑魔法圣殿的地图--"瞬间,队员们被传送到了一个擂台上,最初身边有一 个容量为K的包包. 擂台赛一共有N项挑战,各项挑战依次