Problem:
Problem C:
Adaptive Time Slicing Quantization
Nathan O. Davis is a student at the department of integrated systems. Today he learned digital quanti-
zation in a class. It is a process that approximates analog data (e.g. electrical pressure) by a finite set of
discrete values or integers.
He had an assignment to write a program that quantizes the sequence of real numbers each representing
the voltage measured at a time step by the voltmeter. Since it was not fun for him to implement normal
quantizer, he invented a new quantization method named Adaptive Time Slicing Quantization. This
quantization is done by the following steps:
Divide the given sequence of real numbers into arbitrary
M
consecutive subsequences called
       frames. They do not have to be of the same size, but each frame must contain at least two ele-
       ments. The later steps are performed independently for each frame.
Find the maximum value
V
max
and the minimum value
V
min
of the frame.
Define the set of quantized values. The set contains 2
L
equally spaced values of the interval
       [
V
min
,
V
max
] including the both boundaries. Here,
L
is a given parameter called a
quantization
       level
. In other words, the
i
-th quantized value
q
i
(1 ≤
i
≤ 2
L
) is given by:
.
q
i
=
V
min
+ (
i
- 1){(
V
max
-
V
min
)/(2
L
- 1)}
Round the value of each element of the frame to the closest quantized value.
The key of this method is that we can obtain a better result as choosing more appropriate set of frames in
the step 1. The quality of a quantization is measured by the sum of the squares of the quantization errors
over all elements of the sequence: the less is the better. The quantization error of each element is the
absolute difference between the original and quantized values.
Unfortunately, Nathan caught a bad cold before he started writing the program and he is still down in his
bed. So he needs you help. Your task is to implement Adaptive Time Slicing Quantization instead. In
your program, the quantization should be performed with the best quality, that is, in such a way the sum
of square quantization errors is minimized.
Input
The input consists of multiple datasets. Each dataset contains two lines. The first line contains three
integers
N
(2 ≤
N
≤ 256),
M
(1 ≤
M
≤
N
/2), and
L
(1 ≤
L
≤ 8), which represent the number of
elements in the sequence, the number of frames, and the quantization level. The second line contains
N
real numbers ranging in [0, 1]. The input is terminated by the dataset with
N
=
M
=
L
= 0, which must not be processed.
Output
For each dataset, output the minimum sum of square quantization errors in one line. The answer with an
absolute error of less than or equal to 10
-6
is considered to be correct.
Sample Input
5 2 1
0.1 0.2 0.3 0.4 0.5
6 2 2
0.1 0.2 0.3 0.4 0.5 0.6
0 0 0
Output for the Sample Input
0.01
0.00

Submitted solutions:

code_snippet: // AOJ #2143 Adaptive Time Slicing Quantization
// 2025.3.23

#include <bits/stdc++.h>
using namespace std;
const double INF = 1e12;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int N, M, L;
    while(true) {
        cin >> N >> M >> L;
        if(N==0) break;

        vector<double> v(N);
        for(int i=0; i<N; i++) cin >> v[i];
        vector<vector<double>> err(N, vector<double>(N, 0));
        for(int i=0; i<N; i++){
            double mi = v[i], ma = v[i];
            for(int j = i; j<N; j++){
                mi = min(mi, v[j]);
                ma = max(ma, v[j]);
                double s = 0;
                if(ma - mi < 1e-9) err[i][j] = 0;
                else {
                    int lv = 1 << L;
                    double gap = (ma - mi) / (lv - 1);
                    for(int k = i; k<=j; k++){
                        int idx = (int)round((v[k] - mi) / gap);
                        double q = mi + idx * gap;
                        double d = v[k] - q;
                        s += d * d;
                    }
                    err[i][j] = s;
                }
            }
        }

        vector<vector<double>> dp(M+1, vector<double>(N, INF));
        for(int i=1; i<N; i++) dp[1][i] = err[0][i];
        for(int m=2; m<=M; m++)
            for(int i = 2*m - 1; i < N; i++)
                for(int k = m-2; k <= i-2; k++)
                    if(dp[m-1][k] < INF) dp[m][i] = min(dp[m][i], dp[m-1][k] + err[k+1][i]);

        cout << fixed << setprecision(6) << dp[M][N-1] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 4096
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;

int n, m, l;
vector<double> a;

const int N = 260;
double mem[N][N][N / 2], error[N][N];
int vis[N][N][N / 2], t = 1;

double dp(int i, int j, int k) {
    if (i == n) return (k == m && j == n ? 0 : 1e10);
    auto &ret = mem[i][j][k];
    if (vis[i][j][k] == t) return ret;
    vis[i][j][k] = t;
    ret = dp(i + 1, j, k);
    if (k < m && i - j > 0)
        ret = min(ret, error[j][i] + dp(i + 1, i + 1, k + 1));
    return ret;
}

int main() {
    while (cin >> n >> m >> l) {
        if (!n) break;
        a.resize(n);
        for (auto &i: a) cin >> i;
        for (int i = 0; i < n; ++i) {
            double mx = a[i], mn = a[i];
            for (int j = i + 1; j < n; ++j) {
                mx = max(mx, a[j]), mn = min(mn, a[j]);
                vector<double> q(1 << l);
                for (int k = 0; k < (1 << l); ++k)
                    q[k] = mn + k * (mx - mn) / ((1 << l) - 1);
                error[i][j] = 0;
                for (int k = i; k <= j; ++k) {
                    auto it = upper_bound(q.begin(), q.end(), a[k]);
                    double cd = 1e10;
                    if (it != q.end()) cd = *it - a[k];
                    if (it != q.begin()) {
                        --it;
                        cd = min(cd, a[k] - *it);
                    }
                    error[i][j] += cd * cd;
                }
            }
        }
        cout << fixed << setprecision(9) << dp(0, 0, 0) << '\n';
        t++;
    }
}
accuracy: 1
time_ms: 370
memory_kb: 104032
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

int n, m, l;
vector<double> a;

vector<vector<double>> amx, amn;

double mnquery(int l, int r) {
    int lg = __lg(r - l + 1);
    return min(
            amn[lg][l],
            amn[lg][r - (1 << lg) + 1]
    );
}

double mxquery(int l, int r) {
    int lg = __lg(r - l + 1);
    return max(
            amx[lg][l],
            amx[lg][r - (1 << lg) + 1]
    );
}

const int N = 260;
double mem[N][N][N / 2];
int vis[N][N][N / 2], t = 1;

double dp(int i, int j, int k) {
    if (i == n) return (k == m && j == n ? 0 : 1e10);
    auto &ret = mem[i][j][k];
    if (vis[i][j][k] == t) return ret;
    vis[i][j][k] = t;
    ret = dp(i+1, j, k);
    if (k < m && i - j > 0) {
        double mx = mxquery(j, i), mn = mnquery(j, i);
        vector<double> b(1 << l);
        for (int o = 0; o < (1 << l); ++o)
            b[o] = mn + o * (mx - mn) / ((1 << l) - 1);
        double d{};
        for (int o = j; o <= i; ++o) {
            auto it = upper_bound(b.begin(), b.end(), a[o]);
            double mnd = 1e10;
            if (it != b.end()) mnd = *it - a[o];
            if (it != b.begin()) {
                --it;
                mnd = min(mnd, a[o] - *it);
            }
            d += mnd * mnd;
        }
        ret = min(ret, d + dp(i + 1, i + 1, k + 1));
    }
    return ret;
}


int main() {
    while (cin >> n >> m >> l) {
        if (!n) break;
        a.resize(n);
        for (auto &i: a) cin >> i;
        int max_log = 32 - __builtin_clz(n);
        amn.resize(max_log);
        amx.resize(max_log);
        amn[0] = a;
        amx[0] = a;
        for (int j = 1; j < max_log; ++j) {
            amn[j].resize(n - (1 << j) + 1);
            amx[j].resize(n - (1 << j) + 1);
            for (int i = 0; i + (1 << j) <= n; ++i) {
                amn[j][i] = min(
                        amn[j - 1][i],
                        amn[j - 1][i + (1 << (j - 1))]
                );
                amx[j][i] = max(
                        amx[j - 1][i],
                        amx[j - 1][i + (1 << (j - 1))]
                );
            }
        }
        cout << fixed << setprecision(9) << dp(0, 0, 0) << '\n';
        t++;
    }
}
accuracy: 1
time_ms: 4510
memory_kb: 104068
final_rank: 7

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

const double INF = DBL_MAX / 1000;
const double EPS = 1.0e-10;

int L;
vector<double> a;

double calculateError(int x, int y)
{
    double vMax = 0.0;
    double vMin = 1.0;
    for(int i=x; i<=y; ++i){
        vMax = max(vMax, a[i]);
        vMin = min(vMin, a[i]);
    }

    double ret = 0.0;
    for(int i=x; i<=y; ++i){
        int j = (int)((a[i] - vMin) * (L - 1) / (vMax - vMin) + EPS);
        double q1 = vMin + j * (vMax - vMin) / (L - 1);
        double q2 = vMin + (j + 1) * (vMax - vMin) / (L - 1);

        double d = min(abs(q1 - a[i]), abs(q2 - a[i]));
        d = d * d;
        ret += d;
    }
    return ret;
}

int main()
{
    for(;;){
        int n, m;
        cin >> n >> m >> L;
        if(n == 0)
            return 0;

        L = 1 << L;

        a.resize(n);
        for(int i=0; i<n; ++i)
            cin >> a[i];

        vector<vector<double> > error(n, vector<double>(n));
        for(int i=0; i<n; ++i){
            for(int j=i+1; j<n; ++j){
                error[i][j] = calculateError(i, j);
            }
        }

        vector<vector<double> > dp(n+1, vector<double>(m+1, INF));
        dp[0][0] = 0.0;
        for(int i=0; i<n; ++i){
            for(int j=0; j<m; ++j){
                for(int k=i+1; k<n; ++k){
                    dp[k+1][j+1] = min(dp[k+1][j+1], dp[i][j] + error[i][k]);
                }
            }
        }

        printf("%.10f\n", dp[n][m]);
    }
}
accuracy: 1
time_ms: 960
memory_kb: 1924
final_rank: 2

code_snippet: #include <cstdio>
#include <algorithm>
#include <cmath>
#define REP(i,n) for(int i=0; i<(int)(n); i++)

using namespace std;

const double EPS = 1e-9;

double memo[260][260];
double data[260];
int n, m, l;

double dp[260][260];

inline double dbl(double a){ return a * a; }

int main(){
  while(scanf("%d%d%d", &n, &m, &l), n + m + l){
    REP(i,n) scanf("%lf", data + i);
    for(int len = 2; len <= n; len++){
      for(int start = 0; start + len <= n; start++){
        double mx = *max_element(data + start, data + start + len);
        double mn = *min_element(data + start, data + start + len);
        double dst = (mx - mn) / ((1 << l) - 1);

        double gosa = 0.0;

        if(dst > EPS){
          REP(i,len){
            double sa = data[start + i] - mn;
            int j = (int)floor(sa / dst + 0.5);
            double tmp = 1e10;
            for(int ii = j - 1; ii <= j + 1; ii++)
              tmp = min(tmp, dbl((mn + dst * ii) - data[start + i]));
            gosa += tmp;
          }
        }

        memo[start][start + len] = gosa;
      }
    }

    const double inf = 1e10;
    REP(i,n + 1) REP(j, m + 1)
      dp[i][j] = inf;

    dp[0][0] = 0.0;
    REP(i,n) REP(j,m) if(dp[i][j] != inf){
      for(int len = 2; i + len <= n; len++)
        dp[i + len][j + 1] = min(dp[i + len][j + 1], dp[i][j] + memo[i][i + len]);
    }

    printf("%.8f\n", dp[n][m]);
  }
  return 0;
}
accuracy: 1
time_ms: 2210
memory_kb: 0
final_rank: 3

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define pb         push_back

const int N = 300;
const double inf = 1000;
const double eps=1e-10;

double cost[N][N];
double dp[N][N];

double le(vector<double> &tmp,double tar){
  int l=0,r=tmp.size()-1;
  double ret=-inf;
  while(l <= r){
    int mid=(l+r)/2;
    if (fabs(tmp[mid]-tar)<eps)return tmp[mid];
    else if (tmp[mid] > tar)r=mid-1;
    else l=mid+1,ret=tmp[mid];
  }
  return ret;
}

double ge(vector<double> &tmp,double tar){
  int l=0,r=tmp.size()-1;
  double ret=inf;
  while(l <= r){
    int mid=(l+r)/2;
    if (fabs(tmp[mid]-tar)<eps)return tmp[mid];
    else if (tmp[mid] > tar)r=mid-1,ret=tmp[mid];
    else l=mid+1;
  }
  return ret;
}

void pre(int n,double *in,double div,int L){
  rep(i,n){
    REP(j,i+1,n){
      double maxi=0;
      double mini=10000000;
      cost[i][j]=0;
      for(int k=i;k<=j;k++){
	mini=min(mini,in[k]);
	maxi=max(maxi,in[k]);
      }
      double tmp=(maxi-mini)/div;
      vector<double> hoge;
      REP(k,1,(1<<L)+1){
	hoge.pb(mini+(k-1)*tmp);
      }
      sort(hoge.begin(),hoge.end());
      for(int k=i;k<=j;k++){
	double a=le(hoge,in[k]);
	double b=ge(hoge,in[k]);
	a=(a-in[k])*(a-in[k]);
	b=(b-in[k])*(b-in[k]);
	cost[i][j]+=min(a,b);
      }
    }
  }
}

double solve(int n,int M){
  rep(i,n+1){
    rep(j,M+1)dp[i][j]=inf;
  }
  dp[0][0]=0;
  REP(i,2,n+1){
    REP(j,1,M+1){
      rep(k,i-1){
	dp[i][j]=min(dp[i][j],dp[k][j-1]+cost[k][i-1]);
      }
    }
  }
  return dp[n][M];
}

main(){
  //test();
  int n,M,L;
  double in[N];
  while(cin>>n>>M>>L && n){
    rep(i,n)cin>>in[i];
    pre(n,in,(1<<L)-1,L);
    printf("%.7lf\n",solve(n,M));
  }
  return false;
}
accuracy: 1
time_ms: 4630
memory_kb: 2192
final_rank: 4

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define pb         push_back

const int N = 300;
const double inf = 1000;
const double eps=1e-10;

double cost[N][N];
double dp[N][N];

double le(vector<double> &tmp,double tar){
  int l=0,r=tmp.size()-1;
  double ret=-inf;
  while(l <= r){
    int mid=(l+r)/2;
    if (fabs(tmp[mid]-tar)<eps)return tmp[mid];
    else if (tmp[mid] > tar)r=mid-1;
    else l=mid+1,ret=tmp[mid];
  }
  return ret;
}

double ge(vector<double> &tmp,double tar){
  int l=0,r=tmp.size()-1;
  double ret=inf;
  while(l <= r){
    int mid=(l+r)/2;
    if (fabs(tmp[mid]-tar)<eps)return tmp[mid];
    else if (tmp[mid] > tar)r=mid-1,ret=tmp[mid];
    else l=mid+1;
  }
  return ret;
}

void pre(int n,double *in,double div,int L){
  rep(i,n){
    REP(j,i+1,n){
      double maxi=0;
      double mini=10000000;
      cost[i][j]=0;
      for(int k=i;k<=j;k++){
	mini=min(mini,in[k]);
	maxi=max(maxi,in[k]);
      }
      double tmp=(maxi-mini)/div;
      vector<double> hoge;
      REP(k,1,(1<<L)+1){
	hoge.pb(mini+(k-1)*tmp);
      }
      sort(hoge.begin(),hoge.end());
      //rep(k,hoge.size())cout<<hoge[k]<<" " ;cout <<" !!!"<< endl;
      for(int k=i;k<=j;k++){
	double a=le(hoge,in[k]);
	double b=ge(hoge,in[k]);
	//cout << a <<" " << in[k] <<" " << b << endl;
	a=fabs(a-in[k]);
	b=fabs(b-in[k]);
	if (a<b)cost[i][j]+=a*a;
	else cost[i][j]+=b*b;
	//a=(a-in[k])*(a-in[k]);
	//b=(b-in[k])*(b-in[k]);
	//cost[i][j]+=min(a,b);
      }
    }
  }
}

double solve(int n,int M){
  rep(i,n+1){
    rep(j,M+1)dp[i][j]=inf;
  }
  dp[0][0]=0;
  REP(i,2,n+1){
    REP(j,1,M+1){
      rep(k,i-1){
	//cout << k<<" " << i-1 <<" " << cost[k][i-1] << endl;
	dp[i][j]=min(dp[i][j],dp[k][j-1]+cost[k][i-1]);
      }
    }
  }
  return dp[n][M];
}

main(){
  //test();
  int n,M,L;
  double in[N];
  while(cin>>n>>M>>L && n){
    rep(i,n)cin>>in[i];
    pre(n,in,(1<<L)-1,L);
    printf("%.7lf\n",solve(n,M));
  }
  return false;
}
accuracy: 1
time_ms: 4670
memory_kb: 2188
final_rank: 5