1076: [SCOI2008]奖励关
思路
状压dp,dp[i][s]表示当前是第i次选择,吃过的宝物的状态是s,的期望得分。
如果一个宝物可以吃,那么可以选择吃或不吃,取最大的。
zz的我:50010的空间开成了500100,然后提示tle,醉了。。
代码
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 7 using namespace std; 8 9 double dp[110][50010]; 10 int b[20],w[20]; 11 12 inline int read() { 13 int x = 0,f = 1; char ch = getchar(); 14 for (; !isdigit(ch); ch=getchar()) if(ch=='-') f=-1; 15 for (; isdigit(ch); ch=getchar()) x = x*10+ch-'0'; 16 return x * f; 17 } 18 19 int main() { 20 int m = read(),n = read(); 21 for (int i=1; i<=n; ++i) { 22 w[i] = read(); 23 int tmp = 0,a = read(); 24 while (a) { 25 tmp |= (1<<(a-1)); 26 a = read(); 27 } 28 b[i] = tmp; 29 } 30 31 int t = (1 << n) - 1; 32 for (int i=m; i>=1; --i) { 33 for (int s=t; s>=0; --s) { 34 for (int k=1; k<=n; ++k) { 35 if ((b[k]&s)^b[k]) dp[i][s] += dp[i+1][s]; 36 else dp[i][s] += max(dp[i+1][s],dp[i+1][s|(1<<(k-1))]+w[k]); 37 } 38 dp[i][s] /= double(n); 39 } 40 } 41 printf("%.6lf",dp[1][0]); 42 return 0; 43 }