[关闭]
@wsndy-xx 2018-05-10T10:35:58.000000Z 字数 1393 阅读 1005

Luogu 均分数据

题解

题意

给出 个数, 分成 组,使得均方差最小



Ans 即为均方差


模拟退火


注意

退火时接受非最优解的条件
exp((NowAns - BefAns) / Now_tmep) * MAX_RAND < rand()


Code

  1. #include <bits/stdc++.h>
  2. const int N = 30;
  3. const double Delta = 0.99;
  4. const double eps = 1e-10;
  5. #define DB double
  6. int n, m, A[N], Bel[N];
  7. DB Aver, Answer, Sum[N];
  8. #define gc getchar()
  9. inline int read() {
  10. int x = 0; char c = gc;
  11. while(c < '0' || c > '9') c = gc;
  12. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
  13. return x;
  14. }
  15. inline int Get_short() {
  16. int Min = 1e9, ret;
  17. for(int i = 1; i <= m; ++ i)
  18. if(Sum[i] <= Min) Min = Sum[i], ret = i;
  19. return ret;
  20. }
  21. DB Work() {
  22. DB NowAns = 0;
  23. for(int i = 1; i <= n; ++ i) Sum[i] = 0;
  24. for(int i = 1; i <= n; ++ i) Bel[i] = rand() % m + 1, Sum[Bel[i]] += A[i];
  25. for(int i = 1; i <= m; ++ i) NowAns += (Sum[i] - Aver) * (Sum[i] - Aver);
  26. DB Now_temp = 10000;
  27. while(Now_temp >= eps) {
  28. int shor = std:: min_element(Sum + 1, Sum + m + 1) - Sum, x = rand() % n + 1;
  29. DB BefAns = NowAns;
  30. NowAns -= (Sum[shor] - Aver) * (Sum[shor] - Aver) + (Sum[Bel[x]] - Aver) * (Sum[Bel[x]] - Aver);
  31. Sum[shor] += A[x];
  32. Sum[Bel[x]] -= A[x];
  33. NowAns += (Sum[shor] - Aver) * (Sum[shor] - Aver) + (Sum[Bel[x]] - Aver) * (Sum[Bel[x]] - Aver);
  34. if(NowAns < BefAns || (exp((NowAns - BefAns) / Now_temp) * RAND_MAX < rand())) Bel[x] = shor;
  35. else Sum[shor] -= A[x], Sum[Bel[x]] += A[x], NowAns = BefAns;
  36. Now_temp *= Delta;
  37. }
  38. return NowAns;
  39. }
  40. int main() {
  41. srand(20001206); //meizibaoyou
  42. n = read(), m = read();
  43. for(int i = 1; i <= n; i ++) A[i] = read(), Aver += A[i];
  44. Aver /= m;
  45. int Ty = 1000;
  46. Answer = 1e18;
  47. for(; Ty; Ty --) Answer = std:: min(Answer, Work());
  48. printf("%.2lf", sqrt(Answer / m));
  49. return 0;
  50. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注