// Based on "Optimal k-means Clustering in One Dimension by Dynamic Programming" // (https://journal.r-project.org/archive/2011-2/RJournal_2011-2_Wang+Song.pdf) import java.util.*; import java.io.*; public class Broadband_slow { public static double[][] d; public static int n; public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int m, k, s; double x[]; StringTokenizer st = new StringTokenizer(in.readLine()); m = Integer.parseInt(st.nextToken()); n = Integer.parseInt(st.nextToken()); k = Integer.parseInt(st.nextToken()); s = Integer.parseInt(st.nextToken()); x = new double[m+n+1]; st = new StringTokenizer(in.readLine()); for (int i = 1; i <= m; i++) { x[i] = Double.parseDouble(st.nextToken()); } st = new StringTokenizer(in.readLine()); for (int i = m+1; i <= m+n; i++) { x[i] = Double.parseDouble(st.nextToken()); } Arrays.sort(x); // omit if data are already sorted n = m+n; // Pre-calculate means of all sets {x[i], ..., x[j]} double mu[][] = new double[n+1][n+1]; for (int i = 1; i <= n; i++) { mu[i][i] = x[i]; for (int j = i+1; j <= n; j++) { mu[i][j] = (x[j] +(j-i)*mu[i][j-1])/(j-i+1); } } // Pre-calculate sums of squares of x[i]-mu[i,j], ..., x[j]-mu[i,j] // for all i<= j using nifty formula from aforementioned reference d = new double[n+1][n+1]; for (int i = 1; i <= n; i++) { d[i][i] = 0; for (int j = i+1; j <= n; j++) { d[i][j] = d[i][j-1]+(j-i)*1.0/(j-i+1)*Math.pow(x[j]-mu[i][j-1],2); } } // Look at every partition of x into k subarrays and add up the // sum of square diffs from mean of each subarray double ans = findmin(k,1); // Above used only horizontal differences in location. // Finally, add in squares of vertical distances which are all // identical and equal to (s/2)^2. System.out.println(ans+n*Math.pow(s/2.0,2)); } /////////////////////// // Recursively find smallest k sums of squares in x[j..n] public static double findmin(int k, int j) { if (k==1) { return d[j][n]; } double m = Double.MAX_VALUE; for (int i = j; i <= n-k+1; i++) { double x = findmin(k-1,i+1); m = Math.min(m,d[j][i]+x); } return m; } }