codeforces--698C LRU状压+概率DP

题目链接:https://codeforces.com/problemset/problem/698/C

题目大意:有n种节目,每个节目出现的概率为$p_i$,电视的缓存大小为V,当缓存满了后会挤掉出现次数最少的节目,问在$10^{100}$次询问后每个节目存在缓存中的概率。

Examples

Input
3 1
0.3 0.2 0.5
Output
0.3 0.2 0.5 
Input
2 1
0.0 1.0
Output
0.0 1.0 
Input
3 2
0.3 0.2 0.5
Output
0.675 0.4857142857142857 0.8392857142857143 
Input
3 3
0.2 0.3 0.5
Output
1.0 1.0 1.0 

由于n非常小,所以我们可以直接用二进制枚举缓存中节目的状态,假设dp[sta]表示缓存中存储状态为sta的概率,那么其中第i个1的存在表示第i个节目存在缓存中,我们只需要将每个位数为1的地方做过累加就是每位的最终概率了。

由于$10^{100}$非常大,所以当n个节目中存在非0概率的个数大于缓存容量时缓存一定会爆,而小于等于的时候不会爆,所以每个非零概率的节目都会存在于缓存中

所以我们特判一下小于等于的情况,之后就是对爆的情况做状压。

我们枚举状态sta,当sta中1的个数等于缓存容量的时候就是最终状态了,我们就可以做答案处理,如果sta中1的个数小于缓存容量,那么我们就需要进行状态转移了。也就是对sta中0的元素进行转移即:

for (int j=1; j<=n; j++)
    if ((i&(1<<(j-1)))==0)
        dp[i|(1<<(j-1))]+=dp[i]*p[j]/zros;//有zros份可以补充,其中j占据了p[j]份

也就是对该位的0进行补充,但需要注意的是sta有很多个0要补充,所以我们要将这所有的0位置的概率做个累加记为zros,那么补充该位置的0的概率就是p[j]/zros

那么答案也就很容易出来了

以下是AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const double esp=1e-8;
#define debug printf("@#$#@$#@%#@1^&^**@#$#@%))#%
" )

double p[30],dp[1<<21],ans[30];

int main()
{
    int n,v,cnt=0;
    scanf ("%d%d",&n,&v);
    for (int i=1; i<=n; i++){
        scanf ("%lf",&p[i]);
        if (p[i]>=esp) cnt++;
    }
    if (cnt<=v) {
        for (int i=1; i<=n; i++)
            printf("%.6f%c",p[i]<esp?0.0:1.0,i==n?'
':' ');
        return 0;
    }
    dp[0]=1;
    for (int i=0; i<(1<<n); i++){
        int use=0;
        double zros=0;
        for (int j=1; j<=n; j++){
            if (i&(1<<(j-1))) use++;
            else zros+=p[j];
        }
        if (use>v) continue;
        else if (use==v){
            for (int j=1; j<=n; j++)
                if (i&(1<<(j-1))) 
                    ans[j]+=dp[i];
        }
        else {
            for (int j=1; j<=n; j++)
                if ((i&(1<<(j-1)))==0)
                    dp[i|(1<<(j-1))]+=dp[i]*p[j]/zros;//有zros份可以补充,其中j占据了p[j]份
        }
    }
    for (int i=1; i<=n; i++)
        printf("%.10f%c",ans[i],i==n?'
':' ');
    return 0;
}
路漫漫兮
原文地址:https://www.cnblogs.com/lonely-wind-/p/13235695.html