P2473题解
P2473奖励关
题目大意
自己看
题目分析
首先注意到 \(1 \leq n \leq 15\),很容易可以想到状压。定义一个数组 \(f_{i,j}\) 表示第 \(i\) 轮时状态为 \(j\) 的期望。那么容易想到转移就是直接把上一步的所有可行状态相加再除以状态数,但我们会发现,无法判断此时的选择能否战未来,有后效性无法判断,所以考虑逆推:
\[f_{i,j}=\frac{1}{n} \sum_{k=1}^n \begin{cases} \max(f_{i+1,j},f_{i+1,j|(1<<k-1)}+p_k)(j \& s_k = s_k) \\ f_{i+1,j}(j \& s_k \ne s_k) \end{cases}
\]
即可
代码
#include<bits/stdc++.h>
using namespace std;
//#define int long long
const int N=100+5;
int n,K;
int p[N],s[N];
double f[N][(1<<18)+5];
int main()
{
cin>>K>>n;
for(int i=1;i<=n;i++)
{
cin>>p[i];
int t=1;
while(t)
{
cin>>t;
if(!t)break;
s[i]|=(1<<(t-1));
}
}
for(int i=K;i>=1;i--)
{
for(int j=0;j<(1<<18);j++)
{
for(int k=1;k<=n;k++)
{
if((j&s[k])==s[k])f[i][j]+=max(f[i+1][j],f[i+1][j|(1<<(k-1))]+p[k]);
else f[i][j]+=f[i+1][j];
}
f[i][j]/=n;
}
}
printf("%.6lf",f[1][0]);
}

浙公网安备 33010602011771号