// uva live 4731 // // 状态很好想: // d(i,j)表示前i个网络分为j组所得到的数学期望的最小值 // 转移方程: // d(i,j) = min(d(k,j-1)+cost); // cost由题目给出的条件可知cost = (k+1...i)段的概率和 * i; // // 注意: // 1)肯定概率大的网络分在前面,这样在后面的话,这个大的概率出现在 // 后面的机会就会小。因为每个概率都会至少要算一次,所以先算大的 // 可以尽量减少后面再算大的。 // 2 )初始化的时候只有d(0,0)才是0.0,其他都是inf,因为任意一个不是0的i // 都不可能有d(i,0)这种状况出现; // 感悟: // 总的来说,并不算是很难,只要题目意思看懂了就还行,一直在纠结 // 这个公式是怎么证明的,最后本人实在太笨,只能按照题目给的公式 // 直接硬上喽,如果有人能解答我的疑惑,$2.56小子双手奉上,并致以 // 最为诚挚的感谢 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <functional> #include <iostream> #include <list> #include <map> #include <numeric> #include <queue> #include <set> #include <stack> #include <vector> #define ceil(a,b) (((a)+(b)-1)/(b)) #define endl '\n' #define gcd __gcd #define highBit(x) (1ULL<<(63-__builtin_clzll(x))) #define popCount __builtin_popcountll typedef long long ll; using namespace std; const int MOD = 1000000007; const long double PI = acos(-1.L); int n,w; const int maxn = 180; double d[maxn][maxn]; bool vis[maxn][maxn]; int x[maxn]; double s[maxn]; bool cmp(int x,int y){ return x>y; } double dp(int num,int wi){ if (vis[num][wi]) return d[num][wi]; vis[num][wi] = 1; if (wi==0 || num == 0) return d[num][wi]; for (int i=0;i<=num;i++) d[num][wi] = min(d[num][wi],dp(i,wi-1)+(s[num]-s[i]) * num); return d[num][wi]; } void print(){ for (int i=1;i<=n;i++){ for (int j=1;j<=n;j++){ cout << d[i][j] << " "; } cout << endl; } } void prin(){ for (int i=1;i<=n;i++) cout << s[i] << " "; cout << endl; } void init(){ scanf("%d%d",&n,&w); double sum = 0.0; for (int i=1;i<=n;i++){ scanf("%d",&x[i]); sum +=x[i]; } sort(x+1,x+n+1,cmp); s[0] = 0.0; for (int i=1;i<=n;i++){ s[i] = s[i-1] + x[i]/sum; } //prin(); memset(vis,0,sizeof(vis)); for(int i=0;i<=n;i++) for (int j=0;j<=n;j++){ d[i][j] = 999999999; } d[0][0]=0.0; printf("%.4lf\n",dp(n,w)); //print(); //puts(""); } int main() { int t; //freopen("1.txt","r",stdin); scanf("%d",&t); while(t--){ init(); } return 0; }
时间: 2024-12-19 05:34:44