码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1076 奖励关 状压dp 概率dp

时间:2017-07-25 13:33:08      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:无效   span   就会   ++   pac   zoj   转移   状压dp   选择   

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1076

题意:给出n种物品,每种物品有牵制条件和价值,有k次选择机会,每次每个物品等概率出现,问平均情况下最大收益。(n<=15)

首先看到这个n的范围和限制条件就应该想到是状压。

定义数组f[i][j]为当前处在第i次抛物品时间,状态为j。

但是如果我们仅仅这样定义并正向转移就会遇到一个问题:我们是有可能从无效状态推出有效状态,进而得出错误的结论的。例如,1的限制条件为2、3、4,那么我们就有可能从f[3][0111(2)]推出f[4][1111(2)],进而得出错误的结论。

怎么办呢,倒推。可以确定的是,结尾状态一定是合法的。

技术分享
 1 //以后大概概率都倒推好了……
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 const int maxk=105,maxn=20,maxa=(1<<15);
 8 int n,ka,a[maxn],qianti[maxn];
 9 double f[maxk][maxa];
10 int haha()
11 {
12     scanf("%d%d",&ka,&n);
13     for(int i=1;i<=n;i++)
14     {
15         scanf("%d",&a[i]);int x;
16         while(scanf("%d",&x)!=EOF&&x)
17             qianti[i]|=(1<<(x-1));
18     }
19     int att=(1<<n);
20     for(int i=ka;i;i--)
21         for(int j=0;j<att;j++)
22         {
23             for(int k=1;k<=n;k++)
24                 if((j&qianti[k])==qianti[k])
25                     f[i][j]+=max(f[i+1][j],f[i+1][j|1<<(k-1)]+a[k]);
26                 else f[i][j]+=f[i+1][j];
27             f[i][j]/=n;
28         }
29     printf("%0.6lf\n",f[1][0]);
30 }
31 int sb=haha();
32 int main(){;}
bzoj1076

 

bzoj1076 奖励关 状压dp 概率dp

标签:无效   span   就会   ++   pac   zoj   转移   状压dp   选择   

原文地址:http://www.cnblogs.com/Loser-of-Life/p/7233463.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!