思路:
二进制状压所有的状态,设
f[i][j]
表示当前已经从
1→i−1
当中得到状态
j
<script type="math/tex" id="MathJax-Element-159">j</script>,后面进行选择的最大收益。
转移就是枚举之前的状态,枚举当前出现哪一个元素。
ORZ hzwer
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
double f[110][70010];
int n, m, t, v[20], d[20], p[20];
int main(){
for(int i = 1; i <= 16; i ++) p[i] = 1 << (i-1);
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i ++){
scanf("%d%d", &v[i], &t);
while(t){
d[i] += p[t];
scanf("%d", &t);
}
}
for(int i = n; i; i --){
for(int j = 0; j <= p[m+1]; j ++){
for(int k = 1; k <= m; k ++){
if((d[k]&j) == d[k]){
f[i][j] += max(f[i+1][j], f[i+1][j|p[k]]+v[k]);
}else f[i][j] += f[i+1][j];
}
f[i][j] /= m;
}
}
printf("%.6lf", f[1][0]);
return 0;
}