CodeForces 698 C. LRU(状压DP)

本文介绍了一种计算视频缓存命中率的方法,在给定视频数量、缓存大小及各视频被选中的概率的情况下,通过动态规划算法求解经过大量操作后每个视频在缓存中的概率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description
n个视频,长度为k的缓存,每次询问,每个视频以pi的概率被选,如果不在缓存区则加入,如果缓存区满了,则最先进缓存的出来,问10^100次操作以后每个视频在缓存的概率
Input
第一行两个整数n和k,第二行n个数表示每个视频被选中的概率
(1<=k<=n<=20,0<=pi<=1,sum(pi)=1)
Output
输出10^100次操作后每个视频在缓存中出现的概率
Sample Input
3 1
0.3 0.2 0.5
Sample Output
0.3 0.2 0.5
Solution
倒过来想这些操作,那么问题变成了,如果第i个视频没有出现在缓存中,那么以概率pi被选中放在缓存中,当缓存中视频数量为k时停止,问每个视频出现在缓存中的概率。用一个20位的二进制数表示一个状态,二进制位为1表示对应视频出现在缓存中,为0则没有出现,若某一个状态mark&(1 << i)=0,说明第i个视频在当前状态还没有在缓存中,那么就可以转移到mark|(1 << i)这个状态,转移方程是dp[mark|( 1<< i)]+=dp[mark]*p[i]/sum,其中sum是没有出现在缓存中视频出现概率之和,那么每个视频出现在缓存中的概率就是将所有二进制1个数为k,且该视频对应二进制位为1的状态dp值累加即可
Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 22
#define eps 1e-6
int k,n;
double p[maxn],dp[(1<<20)],ans[maxn]; 
int deal(int x)
{
    int ans=0;
    for(int i=0;i<n;i++)
        if(x&(1<<i))ans++;
    return ans;
}
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        int cnt=0;
        memset(dp,0,sizeof(dp));
        memset(ans,0,sizeof(ans));
        dp[0]=1;
        for(int i=0;i<n;i++)
        {
            scanf("%lf",&p[i]);
            if(p[i]<eps)cnt++;
        }
        k=min(k,n-cnt);
        for(int i=0;i<(1<<n);i++)
        {
            double temp=1;
            for(int j=0;j<n;j++)
                if(i&(1<<j))
                {
                    temp-=p[j];
                    if(deal(i)==k)ans[j]+=dp[i];
                }
            for(int j=0;j<n;j++)
                if((i&(1<<j))==0)
                    dp[i|(1<<j)]+=dp[i]*p[j]/temp;
        }
        for(int i=0;i<n;i++)
            printf("%.7lf%c",ans[i],i==n-1?'\n':' ');
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值