您的位置:首页 > 其它

【BZOJ1076】【SCOI2008】奖励关

2017-05-17 17:48 295 查看

题目大意

  每件物品等概率出现,有条件选择,求最优策略下期望概率。

Solution

  首先,看完题目和数据范围,可以知道这是一个期望DP。我一开始从前往后推,然后发现怎么都推不出来,卡了半天……TAT。

  原因在于,后面可能的状态会影响前面的选择,每一次的选择都跟后面可能的状态和前面的状态有关。那么如果倒着推,对于一定的状态来说,后面的最优策略已经确定,只要枚举前面所有可能的状态,判断每个后继状态最优的答案。这样,虽然有一部分计算是冗余的(即不可能出现),但在计算过程中只会把需要的部分加入答案。

  

#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<string>
#include<cstdio>
#include<vector>
#include<bitset>
#include<iomanip>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rep(i,a,b) for (int i=a; i<=b; i++)
#define per(i,a,b) for (int i=a; i>=b; i--)
using namespace std;
typedef long long LL;

inline int read() {
int x=0,f=1; char ch=getchar();
while (!(ch>='0'&&ch<='9')) {if (ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+(ch-'0'); ch=getchar();}
return x*f;
}

const int N = 105;
const int M = 1<<15;
const int C = 15;

int K,n;
int val[C],need[C];
double dp
[M],P;

int main() {

#ifndef ONLINE_JUDGE
//  freopen("data.in","r",stdin);
//  freopen("data.out","w",stdout);
#endif

K=read(),n=read();
rep(i,0,n-1) {
val[i]=read(); int sta=0;
while (true) {
int x=read(); x--;
if (x==-1) break;
sta|=(1<<x);
}
need[i]=sta;
}

P=1.0/n;
per(i,K-1,0) {
rep(j,0,(1<<n)-1) {
rep(k,0,n-1) {
if ((need[k]&j)==need[k]) dp[i][j]+=max(dp[i+1][j|(1<<k)]+val[k],dp[i+1][j])*P;
else dp[i][j]+=dp[i+1][j]*P;
}
}
}

printf("%.6lf\n",dp[0][0]);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: