Title Link: BZOJ-2428
Problem analysis
This problem is done using a randomized algorithm, which can be simulated with annealing or random_shuffle after the greedy.
Simulated annealing:
To perform multiple simulated annealing, randomly assign a collection to each point before each simulated annealing.
Then the random movement of the simulated annealing is a random point, then another set Y is found, and the point is moved to the set Y.
The movement of simulated annealing at the beginning results in a larger range of answers, at which point the set Y takes the smallest set directly and a random set Y at a later stage.
Note that if the answer is the same as the current answer after the move, move the past. This is to avoid staying on the flat plateau topography .
Random_shuffle + greedy:
The process of Random_shuffle + greed can find the optimal solution more than once.
Code
Simulated annealing:
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath > #include <algorithm>using namespace std;const int maxn = + 5;typedef double db;int n, M;int A[maxn], belong[m AxN];D b Ans, ave;db Sum[maxn];inline db SQR (db x) {return x * x;} Inline DB Rand () {return (DB) (rand ()% 10000)/10000.0;} void SA () {memset (sum, 0, sizeof (sum)), for (int i = 1; I <= n; ++i) {Belong[i] = rand ()% m + 1; Sum[belong[i]] + = (DB) a[i];} DB t = 10000;int T, x, Y;db DE, Temp, Num; num = 0;for (int i = 1; I <= m; ++i) num + SQR (sum[i]-Ave); if (Num < ans) ans = num;while (T > 0.1) {t *= 0.9;t = rand ()% n + 1;x = belong[t];if (T > x) {y = 1; temp = sum[1];for (int i = 2; I <= m; ++i) {if (Sum[i] < temp) {temp = Sum[i];y = i;}}} Else y = rand ()% m + 1;if (y = = x) continue; Temp = Num; Temp-= SQR (Sum[x]-Ave) + SQR (Sum[y]-Ave); Temp + = SQR (Sum[x]-a[t]-Ave) + SQR (Sum[y] + a[t]-Ave); if (temp < ans) ans = Temp;de = num-tEmp;if (DE >= 0 | | Rand () < exp (de/t)) {Num = Temp; SUM[X]-= a[t]; Sum[y] + = a[t]; Belong[t] = y;}} if (num < ans) ans = num;} int main () {srand (80458946); scanf ("%d%d", &n, &m); for (int i = 1; I <= n; ++i) {scanf ("%d", &a[i]); Ave + = (DB) a[i];} Ave/= m; Ans = 1e50;for (int i = 1; I <= 10000; ++i) SA ();p rintf ("%.2lf\n", sqrt (ans/m)); return 0;}
Random_shuffle + greedy:
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath > #include <algorithm>using namespace std;const int maxn = + 5;typedef double db;int n, m;int a[maxn];inline DB SQR (DB x) {return x * x;} DB Ave, Ans;db Solve () {db p, q, sum = 0, ret = 0, Cnt = 1;int i;for (i = 1; I <= n && Cnt < m; ++i) {if (sum + (db) a[i] >= Ave) {p = SQR (Sum + (db) a[i]-Ave); q = SQR (Sum-ave); if (P < q) {ret + = p; Sum = 0;} Else{ret + = q; Sum = A[i];} ++cnt;} else Sum + = (DB) a[i];} for (; I <= n; ++i) Sum + = (DB) A[i];ret + = SQR (sum-ave); return sqrt (ret/m);} int main () {scanf ("%d%d", &n, &m); for (int i = 1; I <= n; ++i) {scanf ("%d", &a[i]); Ave + = (DB) a[i];} Ave/= m; Ans = 1e50;for (int i = 1; I <= 500000; ++i) {random_shuffle (A + 1, a + n + 1); ans = min (ans, Solve ());} printf ("%.2lf\n", Ans); return 0;}
[Bzoj 2428] [HAOI2006] Sharing data