zoukankan      html  css  js  c++  java
  • bzoj 1076

    发现自己已经把期望dp忘光了...

    其实本质上非常简单,就是利用状压的思想跑期望

    首先很容易设计出状态:记状态f[s][i]表示到了第i个点,之前已选过的点的状态为s时所能获得的最大期望得分

    但是会发现这样做没法转移(你可以试一下,我做了半个点做得原地爆炸)

    但是我们知道,期望dp常见的策略是从后向前,逆向转移

    所以我们修改一下状态:记状态f[s][i]表示到了第i个点选的点集为s时,i-k所能获得的最大期望

    这样有转移方程:

    large f[s][i]+=max(f[s][i+1],f[s|(1<<(x-1))][i+1]+v[x])(x的前提在s中)

    large f[s][i]+=f[s][i+1](x的前提不在s中)

    最后将f[s][i]除以n,得到的即为答案

    最后输出f[0][1]即可

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    using namespace std;
    double dp[105][(1<<15)+5];
    double f[(1<<15)+5];
    int k,n;
    int sit[20];
    double v[20];
    int main()
    {
    	scanf("%d%d",&k,&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lf",&v[i]);
    		while(1)
    		{
    			int x;
    			scanf("%d",&x);
    			if(!x)
    			{
    				break;
    			}
    			sit[i]|=(1<<(x-1));
    		}
    	}
    	for(int i=k;i>=1;i--)
    	{
    		for(int j=0;j<(1<<n);j++)
    		{
    			for(int o=1;o<=n;o++)
    			{
    				if((sit[o]&j)==sit[o])
    				{
    					dp[i][j]+=max(dp[i+1][j|(1<<(o-1))]+v[o],dp[i+1][j]);
    				}else
    				{
    					dp[i][j]+=dp[i+1][j];
    				}
    			}
    			dp[i][j]*=1.0/(double)n;
    		}
    	}
    	printf("%.6lf
    ",dp[1][0]);
    	return 0;	
    }
  • 相关阅读:
    channel分析
    Nginx|基础
    item2
    搜索引擎技巧
    计算机网络|概述
    操作系统|进程
    分布式事务一致性
    画图工具StartUML
    内存分配
    MPG分析
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10764147.html
Copyright © 2011-2022 走看看