uva 1456 dp 求期望

来源:互联网 发布:oracle sql优化 编辑:程序博客网 时间:2024/05/01 17:34
UVA 1456 - Cellular Network

大致意思可以理解为有n个盒子,盒子里面放球的概率为p[i],把这n个盒子分成k组,按顺序打开每组的盒子。求打开盒子找到球的需要拆盒子数的期望。

按概率从大道小排序,贪心选择概率大的盒子先拆,然后维护概率的前缀和。
dp[i][j]表示前i个盒子被分成j组的找到小球的期望。


dp[i][j] = min{dp[k][j-1] + (p[i] - p[k]) * i};


#include <bits/stdc++.h>using namespace std;const int INF = 999999999;int n, m;int a[105];double p[105];double dp[105][105];int _sum;bool cmp (double a, double b) {return a > b;} int main () {int T;for (scanf ("%d", &T); T>0; --T) {scanf("%d%d", &n, &m);_sum = 0;for (int i=1; i<=n; i++) {scanf ("%d", &a[i]);_sum += a[i];}for (int i=1; i<=n; i++) {p[i] = 1.0 * a[i] / _sum;}sort(p+1, p+n+1, cmp);for (int i=1; i<=n; i++) {p[i] += p[i-1];}dp[1][1] = p[1] * 1.0;for (int i=2; i<=n; i++) {dp[i][1] = p[i] * i; for (int j=2; j<=min(i, m); j++) {dp[i][j] = INF * 1.0;for (int k=j-1; k<i; k++) {dp[i][j] = min(dp[i][j], dp[k][j-1] + 1.0 * (p[i] - p[k]) * i);}}}printf("%.4lf\n", dp[n][m]);}return 0;}


0 0