zoukankan      html  css  js  c++  java
  • 概率dp+状压dp C. LRU 暑训第五天

    C. LRU 概率dp+状压dp

    题目大意:

    有一个缓存,它最多可以存k条记录,如果超过k条记录,那么最早存进去的记录会被删除,如果其中有一条记录之前已经存过,那么会更新这条记录的时间,并且将之前的那条记录删除。

    第一行,给你n条记录和缓存的大小k,第二行,给你每条记录存进缓存的概率,问经过无穷次存储之后,最后每条记录存进缓存的概率。

    题解:

    这种概率题目我其实很不擅长,又涉及到无穷,更是一头雾水。。。

    从后往前考虑!!!考虑最后是一个什么样的状态

    考虑中间状态形成的原因以及概率的求法:

    • 第一种:自增,假设原来缓存已经有1、2,那么又变成1、2这种状态是可以1这条记录或者2这条记录加进缓存,这个就是自增
    • 第二种:其他状态转移过来,假设状态是1、2,那么是不是可以从两种状态转移过来,第一种就是缓存1这条记录,第二种就是缓存有2这条记录

    考虑最后状态形成的原因以及概率的求法:

    • 这个最后一个状态和中间状态肯定是不一样的,因为最后一个状态确定之后,这个缓存就不会改变了,因为都已经是最后的状态了,这个时候就只需要求最后状态的概率。

    • 最后的这个状态是肯定不会是自增形成的,因为如果是自增,那么永远填不满这k个值,因为重复的元素要被删除。所以最后一个状态只能从其他状态转移过来。

    知道这些之后就可以列式子了,

    (dp[i]=sum(p[j])*dp[i]+sum(dp[i igotimes (1<<j)]*p[j]))

    因为 (dp[i]) 表示 (i) 这种状态的出现的概率之和,所以 (dp[0]=1) 因为一开始的(dp[0]=1) 之后永远都不会出现缓存是0条记录的情况,所以可知 (dp[0]=1)

    #include <bits/stdc++.h>
    #define id first
    #define val second
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn=25;
    const double eps = 1e-8;
    typedef long long ll;
    double dp[1<<21],p[maxn],ans[maxn];
    
    int main(){
        int n,k,now=0;
        scanf("%d%d",&n,&k);
        for(int i=0;i<n;i++) {
        	scanf("%lf",&p[i]);
        	if(p[i]>eps) now++;
        }
        dp[0]=1;
        k=min(k,now);
        for(int i=1;i<(1<<n);i++){
            int x= i,num=0;
            double sum=0,res=1.0;
            for(int j=0;j<n;j++){
                int tmp=x&(1<<j);
                if(tmp) {
                    num++;
                    res-=p[j];
                    sum+=p[j]*dp[x^(1<<j)];
                }
            }
            if(num==k) {
    //        	printf("kk   dp[%d]=%f sum=%f res=%f
    ",i,dp[i],sum,res);
                dp[i]=sum;
                for(int j=0;j<n;j++){
                    int tmp=x&(1<<j);
                    if(tmp) ans[j]+=dp[i];
                }
            }
            if(num<k) dp[i]=sum/res;
    //        if(!((i&(1<<3))||(i&(1<<5))||(i&(1<<7))||(i&(1<<9))
    //		||(i&(1<<11))||(i&(1<<13))||(i&(1<<15))||(i&(1<<16))||(i&(1<<17))||(i&(1<<18))||(i&(1<<19)))){
    //        	printf("dp[%d]=%f sum=%f res=%f
    ",i,dp[i],sum,res);
    //
    //		}
        }
        for(int i=0;i<n;i++) printf("%.10f ",ans[i]);
        printf("
    ");
    }
    
    
  • 相关阅读:
    201671010116. 2016-2017-10《Java程序设计》第10周学习总结
    201671010116. 2016-2017-8《Java程序设计》第9周学习总结
    201671010116. 2016-2017-8《Java程序设计》第8周学习总结
    Java学习计划
    201671010114 2016-2017-2 《Java程序设计》学习总结
    2016-2017-2 《Java程序设计》第十六周学习总结
    201671010114 2016-2017-2 《Java程序设计》第十五周学习总结
    201671010114 2016-2017-2 《Java程序设计》第十四周学习总结
    201671010114 2016-2017-2 《Java程序设计》第十三周学习总结
    201671010114 2016-2017-2 《Java程序设计》第十二周学习总结
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13261238.html
Copyright © 2011-2022 走看看