Link:
Solution:
数据范围就是题解
能比较明显看出是一道期望+状压的题目
一开始想正向推公式,结果发现每一阶段的答案并不符合后项无关性……
其实在题面中就有所提示,当前的最优解并不一定是总的最优解
这种情况下可以考虑反向$dp$来保证最优解
其中$dp[i][s]$表示当前状态为$s$,从第$i$个数到末尾的最大权值
记得每次统计完后除以$n$就好了
Code:
#include <bits/stdc++.h> using namespace std; double dp[105][1<<16]; int k,n,x,dat[105],st[105]; int main() { scanf("%d%d",&k,&n); for(int i=1;i<=n;i++) { scanf("%d",&dat[i]); while(scanf("%d",&x)!=EOF&&x) st[i]+=(1<<x-1); } int MAX=(1<<n)-1; for(int i=k;i>=1;i--) for(int j=0;j<=MAX;j++) { for(int l=1;l<=n;l++) if((j&st[l])==st[l]) dp[i][j]+=max(dp[i+1][j],dp[i+1][j|(1<<l-1)]+dat[l]); else dp[i][j]+=dp[i+1][j]; dp[i][j]/=(double)n; } printf("%.6lf",dp[1][0]); return 0; }