【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; }
相关文章推荐
- BZOJ1076: [SCOI2008]奖励关
- bzoj 1076: [SCOI2008]奖励关 (期望dp)
- 【bzoj1076】[SCOI2008]奖励关
- bzoj 1076: [SCOI2008]奖励关 期望dp+状态压缩
- bzoj 1076: [SCOI2008] 奖励关 题解
- 【bzoj1076】[SCOI2008]奖励关 状压DP
- bzoj 1076: [SCOI2008]奖励关
- BZOJ 1076: [SCOI2008]奖励关(期望+状压DP)
- bzoj1076: [SCOI2008]奖励关(期望dp+状压dp)
- bzoj1076: [SCOI2008]奖励关 压状dp
- BZOJ1076:[SCOI2008]奖励关——题解
- BZOJ 1076:[SCOI2008]奖励关
- [BZOJ1076][SCOI2008]奖励关 状压dp
- BZOJ1076 [SCOI2008]奖励关 【状压dp + 数学期望】
- ●BZOJ 1076 [SCOI2008]奖励关
- 【bzoj 1076】: [SCOI2008]奖励关
- BZOJ1076 [SCOI2008] 奖励关
- bzoj1076 [SCOI2008]奖励关(期望+dp)
- bzoj-1076[SCOI2008]奖励关
- bzoj1076 [SCOI2008]奖励关