题目大意:
给出数字的个数n以及要分成的组数w。
然后给出各个数字的概率,
求最小的数学期望。
思路:
DP。因为要求最小的数学期望所以概率大的应该摆在前面,所以要先排序一下。
dp[i][j]表示的是第i组前j个数字可以得到的最小的数学期望。
代码:
#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>
#include <algorithm>
const int INF = 0x3f3f3f3f;
const int maxn = 105;
int f[maxn][maxn];
int num[maxn],sum[maxn];
bool cmp(int a,int b) {
return a > b;
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
int n,w;
scanf("%d %d",&n,&w);
for(int i = 1; i <= n; i++)
scanf("%d",&num[i]);
sort(num + 1, num + 1 + n,cmp);
sum[1] = num[1];
for(int i = 2; i <= n ; i++)
sum[i] = num[i] + sum[i - 1];
for(int i = 1; i <= w; i++) {//组数
for(int j = i ; j <= i + n -w; j++) {//取前j个数字 为什么<= i + n - w是因为至少要留下w - i个数字才可以让后面的组有数字,所以j只能取n - (w - i)即i + n - w
if(i == 1) {//如果是第一组的话就直接算
f[i][j] = j * sum[j];
continue;
}
f[i][j] = INF;
for(int k = i - 1; k < j ; k++)
f[i][j] = min(f[i][j],f[i - 1][k] + j *(sum[j] - sum[k]));//求出不同划分中最小的那个
}
}
//printf("%d\n",f[w][n]);
double ans = f[w][n]/100.0;
printf("%.4lf\n",ans);
}
return 0;
}