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

7.16T1

时间:2019-07-17 16:56:36      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:img   font   图片   cst   code   spl   gif   splay   取出   

这是道水题!?反正大佬说它水,那他就水着吧,我反正没觉得

我是实在没想到这道题就码了30行,不过这道题证明我现在对状压有了一丝丝敏感度,想到了要状压,并且想出了状压的状态,然而我连题都没看懂,样例也没搞出来,就随便骗了点分

这道题的状态就是用1代表这件商品被买过了,0表示没买过,由于他每次拿出哪件物品的都有可能,当然了也可能什么都没拿出来,那这个状态就有3个来源

1.这次买到了没买过的物品

2.这次买到了买过的物品

3.这次什么也没买到

其实2和3是一样的,都是由当前状态转移到当前状态,不过2和3共同的概率我们不可能直接得到,那就只能用1减去第一种情况出现的概率,我们试着列一下转移方程

f[i]=∑(f[i-j]*p[j])+(1-∑p[j])*f[i]+1

这个东西有了上面那些应该就很好理解了j代表的是取出来的那个1,当然必要时要把它变成第j件物品,也就是它是第几个一,这个应该是状压的常见套路吧,这个+1是因为不管你从那个状态来你都要多买一次,其实这个+1就看你怎么理解了,他应该是可以有不同的理解方式,我们给这个式子移一下项,他就变成了整个样子

f[i]=(∑(f[i-j]*p[j])+1) / ∑p[j]

然后愉快的转移就好了

技术图片
 1 #include<iostream>
 2 #include<cstdio>
 3 #define ll long long
 4 #define maxn 22
 5 using namespace std;
 6 int n;
 7 ll ans;
 8 int c[1<<maxn];
 9 ll W[maxn];
10 double gl[maxn],f[1<<maxn];
11 int lowbit(int x)
12 {
13     return x&(-x);
14 }
15 int main()
16 {
17     scanf("%d",&n);
18     for(int i=0;i<n;++i)  {int ls=(1<<i);  c[ls]=i+1;}
19     for(int i=1;i<=n;++i)  {scanf("%lf%lld",&gl[i],&W[i]);  ans+=W[i];}
20     printf("%lld\n",ans);
21     for(int i=1;i<(1<<n);++i)
22     {
23         double sum=0;
24         for(int k=i;k;k-=lowbit(k))
25         {
26             int ls1=lowbit(k);  int ls2=c[ls1];
27             f[i]+=f[i-ls1]*gl[ls2];  sum+=gl[ls2];
28         }
29         f[i]=(f[i]+1.000)/sum;
30     }
31     printf("%0.3lf\n",f[(1<<n)-1]);
32     return 0;
33 }
View Code

 

7.16T1

标签:img   font   图片   cst   code   spl   gif   splay   取出   

原文地址:https://www.cnblogs.com/hzjuruo/p/11201870.html

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