zoukankan      html  css  js  c++  java
  • bzoj1076 奖励关 状压dp 概率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
    ",f[1][0]);
    30 }
    31 int sb=haha();
    32 int main(){;}
    bzoj1076
    只要是活着的东西,就算是神我也杀给你看。
  • 相关阅读:
    ZOJ 1450
    HDU 3932
    POJ 3348
    POJ 1873
    POJ 1228
    POJ 2007
    POJ 1113
    POJ 1696
    POJ 1329
    HDU 3432
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7233463.html
Copyright © 2011-2022 走看看