POJ 3028 Shoot-out
Posted in PKU OJ on 四月 27th, 2010 by 纳米 – 1 Comment2010-04-24,阅读题目、解题报告
2010-04-26,与老师讨论,阅读标程,Code,Debug
2010-04-27,提交,AC。本地搞到数据测用600ms,记得比POJ快的,于是想能进1000ms就不错了(因为另一份用解方程方法解决环的程序说用了2000ms),结果提交,250ms。我记得我阅读题目的时候最快的是3xxms,莫非……一看,果然刷了个第一。为了庆祝一下,写一份详细的解题报告。
(用文档写,稍后上传PDF)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #include <stdio.h> #include <string.h> const int pow[] = {1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7, 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13}; const int maxn = 13; int Statu[maxn + 1][1 << maxn][maxn], StatuSize[maxn][1 << maxn], Next[maxn+1][1 << maxn][maxn]; int n; double p[maxn], dp[maxn][1 << maxn][maxn]; int init() { memset(StatuSize, 0, sizeof(StatuSize)); for (int i = 1; i <= maxn; ++i) for (int s = 1; s < pow[i]; ++s) for (int j = 0; j < i; ++j) if (s & pow[j]) Statu[i][s][StatuSize[i][s]++] = j; for (int i = 1; i <= maxn; ++i) for (int s = 1, jj, j; s < pow[i]; ++s) { for (jj = 0, j = Statu[i][s][0]; jj < StatuSize[i][s]-1; j = Statu[i][s][++jj]) Next[i][s][j] = Statu[i][s][jj+1]; Next[i][s][j] = Statu[i][s][0]; } return 0; } int input() { scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%lf", &p[i]); p[i] /= 100; } return 0; } void calc_root(double *root[], double cf1[], double cf2[], int n) { double cf1x = cf1[0], cf2x = cf2[0]; for (int i = 1; i < n; ++i) { cf2x += cf1x * cf2[i]; cf1x *= cf1[i]; } if (1-1e-12 < cf1x && cf1x < 1+1e-12) *root[0] = 1; else *root[0] = cf2x / (1 - cf1x); for (int i = n-1; i > 0; --i) *root[i] = cf2[i] + cf1[i] * *root[i+1 < n ? i+1 : 0]; } int work() { for (int s = 1; s < pow[n]; ++s) { double hit[maxn][maxn]; for (int ii = 0, i = Statu[n][s][0]; ii < StatuSize[n][s]; i = Statu[n][s][++ii]) { double px = 0, px0; int t[maxn], ts[maxn], ps = 0, ns; for (int jj = 0, j = Statu[n][s][0]; jj < StatuSize[n][s]; j = Statu[n][s][++jj]) { ns = s - pow[j]; px0 = i != j ? dp[i][ns][Next[n][ns][i]] : -1; if (px - 1e-12 < px0 && px0 < px + 1e-12) { t[++ps] = j; ts[ps] = ns; } else if (px0 > px + 1e-12) { px = px0; t[ps=1] = j; ts[ps] = ns; } } for (int jj = 0, j = Statu[n][s][0]; jj < StatuSize[n][s]; j = Statu[n][s][++jj]) { hit[i][j] = 0; for (int k = 1; k <= ps; ++k) hit[i][j] += pow[j] & ts[k] ? dp[j][ts[k]][Next[n][ts[k]][i]] : 0; if (ps) hit[i][j] *= p[i] / ps; else hit[i][j] = p[i]; } } for (int ii = 0, i = Statu[n][s][0]; ii < StatuSize[n][s]; i = Statu[n][s][++ii]) { double * root[maxn], cf1[maxn], cf2[maxn]; int k = 0; for (int jj = 0, j = Statu[n][s][0]; jj < StatuSize[n][s]; j = Statu[n][s][++jj]) { root[k] = &dp[i][s][j]; cf1[k] = 1 - p[j]; cf2[k++] = hit[j][i]; } calc_root(root, cf1, cf2, k); } } return 0; } int output() { for (int i = 0; i < n-1; ++i) printf("%.2f ", dp[i][pow[n]-1][0] * 100); printf("%.2f\n", dp[n-1][pow[n]-1][0] * 100); return 0; } int main() { init(); int Cases; scanf("%d", &Cases); while (Cases--) { input(); work(); output(); } return 0; } |