Problem:
3D Printing
We are designing an installation art piece consisting of 
a number of cubes with 3D printing technology for submitting one to
Installation art Contest with Printed Cubes (ICPC).
At this time, we are trying to model a piece consisting of exactly
k
cubes 
of the same size facing the same direction.
First, using a CAD system, 
we prepare
n
(
n
≥
k
) positions as candidates
in the 3D space where cubes can be placed.

When cubes would be placed at all the candidate positions, 
the following three conditions are satisfied.
Each cube may overlap zero, one or two other cubes, but not three or more.
When a cube overlap two other cubes, those two cubes do not overlap.
Two non-overlapping cubes do not touch at their surfaces, edges or corners.
Second, choosing appropriate
k
different positions from
n
candidates
and placing cubes there, 
we obtain a connected polyhedron as a union of the
k
cubes. 

When we use a 3D printer,
we usually print only the thin surface of a 3D object.

In order to save the amount of filament material for the 3D printer, 
we want to find the polyhedron with the minimal surface area.
Your job is to find the polyhedron with the minimal surface area
consisting of
k
connected
cubes placed at
k
selected positions among
n
given ones.
Figure E1. A polyhedron formed with connected identical cubes.
Input
The input consists of multiple datasets. 
The number of datasets is at most 100.
Each dataset is in the following format.
n
k
s
x
1
y
1
z
1
...
x
n
y
n
z
n
In the first line of a dataset,
n
is the number of the candidate positions,
k
is the number of the cubes to form the connected polyhedron,
and
s
is the edge length of cubes.
n, k
and
s
are integers separated by a space. 
The following
n
lines specify the
n
candidate positions.
In the
i
-th line, there are three integers
x
i
,
y
i
and
z
i
that specify the coordinates of a position,  
where the corner of the cube with the smallest coordinate values
may be placed.
Edges of the cubes are to be aligned with either of three axes.
All the values of coordinates are integers separated by a space.

The three conditions on the candidate positions mentioned above are satisfied.
The parameters satisfy the following conditions:
1 ≤
k
≤
n
≤ 2000, 3 ≤
s
≤ 100,  and
-4×10
7
≤
x
i
,
y
i
,
z
i
≤ 4×10
7
.
The end of the input is indicated by a line containing three zeros
separated by a space.
Output
For each dataset, output a single line containing one integer
indicating the surface area of the connected polyhedron with 
the minimal surface area.

When no
k
cubes form a connected polyhedron, output -1.
Sample Input
1 1 100
100 100 100
6 4 10
100 100 100
106 102 102
112 110 104
104 116 102
100 114 104
92 107 100
10 4 10
-100 101 100
-108 102 120
-116 103 100
-124 100 100
-132 99 100
-92 98 100
-84 100 140
-76 103 100
-68 102 100
-60 101 100
10 4 10
100 100 100
108 101 100
116 102 100
124 100 100
132 102 100
200 100 103
192 100 102
184 100 101
176 100 100
168 100 103
4 4 10
100 100 100
108 94 100
1
...(truncated)

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;

namespace atcoder {

// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
  public:
    dsu() : _n(0) {}
    explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}

    int merge(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
        parent_or_size[x] += parent_or_size[y];
        parent_or_size[y] = x;
        return x;
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return leader(a) == leader(b);
    }

    int leader(int a) {
        assert(0 <= a && a < _n);
        if (parent_or_size[a] < 0) return a;
        return parent_or_size[a] = leader(parent_or_size[a]);
    }

    int size(int a) {
        assert(0 <= a && a < _n);
        return -parent_or_size[leader(a)];
    }

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = leader(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                           [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }

  private:
    int _n;
    // root node: -1 * component size
    // otherwise: parent
    std::vector<int> parent_or_size;
};

}  // namespace atcoder
/* BOOST MULTIPRECISION
#include<boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision;
//*/

typedef long long ll;

#define rep(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) begin(v),end(v)

template <typename T> bool chmin(T &a, const T &b) {
	if (a <= b) return false;
	a = b;
	return true;
}

template <typename T> bool chmax(T &a, const T &b) {
	if (a >= b) return false;
	a = b;
	return true;
}

template <typename T> T max(vector<T> &a){
	assert(!a.empty());
	T ret = a[0];
	for (int i=0; i<(int)a.size(); i++) chmax(ret, a[i]);
	return ret;
}

template <typename T> T min(vector<T> &a){
	assert(!a.empty());
	T ret = a[0];
	for (int i=0; i<(int)a.size(); i++) chmin(ret, a[i]);
	return ret;
}

template <typename T> T sum(vector<T> &a){
	T ret = 0;
	for (int i=0; i<(int)a.size(); i++) ret += a[i];
	return ret;
}

// importbisect
template <typename T>
int bisect_left(vector<T> &X, T v){
	return lower_bound(X.begin(), X.end(), v) - X.begin();
}

template <typename T>
int bisect_right(vector<T> &X, T v){
	return upper_bound(X.begin(), X.end(), v) - X.begin();
}
// ----

// defcomp
template <typename T>
vector<T> compress(vector<T> &X) {
	vector<T> vals = X;
	sort(vals.begin(), vals.end());
	vals.erase(unique(vals.begin(), vals.end()), vals.end());
	return vals;
}
// -----

// makediv
vector<ll> makediv(ll n){
	vector<ll> ld, ud;
	for (ll i=1; i*i<=n; i++){
		if (n%i == 0){
			ld.push_back(i);
			if (i != n/i){
				ud.push_back(n/i);
			}
		}
	}
	reverse(ud.begin(), ud.end());
	ld.insert(ld.end(), ud.begin(), ud.end());
	return ld;
}
// -----

// Fast Factorization
// https://judge.yosupo.jp/submission/38126
// !!! CHANGED THE PRIMARY TEST !!!
typedef unsigned int uint;

struct Mint {
	uint64_t n;
	static uint64_t mod, inv, r2;
	Mint() : n(0) { }
	Mint(const uint64_t &x) : n(init(x)) { }
	static uint64_t init(const uint64_t &w) { return reduce(__uint128_t(w) * r2); }
	static void set_mod(const uint64_t &m) {
		mod = inv = m;
		for(int i = 0; i < 5; i++)	inv *= 2 - inv * m;
		r2 = -__uint128_t(m) % m;
	}
	static uint64_t reduce(const __uint128_t &x) {
		uint64_t y = uint64_t(x >> 64) - uint64_t((__uint128_t(uint64_t(x) * inv) * mod) >> 64);
		return int64_t(y) < 0 ? y + mod : y;
	}
	Mint& operator+= (const Mint &x) { n += x.n - mod; if(int64_t(n) < 0) n += mod; return *this; }
	Mint& operator+ (const Mint &x) const { return Mint(*this) += x; }
	Mint& operator*= (const Mint &x) { n = reduce(__uint128_t(n) * x.n); return *this; }
	Mint& operator* (const Mint &x) const { return Mint(*this) *= x; }
	uint64_t val() const { return reduce(n); }
};

uint64_t Mint::mod, Mint::inv, Mint::r2;

bool suspect(const uint64_t &a, const uint64_t &s, uint64_t d, const uint64_t &n) {
	if(Mint::mod != n)	Mint::set_mod(n);
	Mint x(1), xx(a), o(x), m(n - 1);
	while(d > 0) {
		if(d & 1)	x *= xx;
		xx *= xx;
		d >>= 1;
	}
	if(x.n == o.n)	return true;
	for(uint r = 0; r < s; r++) {
		if(x.n == m.n)	return true;
		x *= x;
	}
	return false;
}

bool is_prime(const uint64_t &n) {
	if(n <= 1 || (n > 2 && (~n & 1)))	return false;
	uint64_t d = n - 1, s = 0;
	while(~d & 1)	s++, d >>= 1;
	static const uint64_t a_big[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
	static const uint64_t a_smo[] = {2, 7, 61};
	if(n < 4759123141LL) {
		for(auto &&p : a_smo) {
			if(p >= n)	break;
			if(!suspect(p, s, d, n))	return false;
		}
	} else {
		for(auto &&p : a_big) {
			if(p >= n)	break;
			if(!suspect(p, s, d, n))	return false;
		}
	}
	return true;
}

uint64_t rho_pollard(const uint64_t &n) {
	if(~n & 1)	return 2u;
	static random_device rng;
	uniform_int_distribution<uint64_t> rr(1, n - 1);
	if(Mint::mod != n)	Mint::set_mod(n);
	for(;;) {
		uint64_t c_ = rr(rng), g = 1, r = 1, m = 500;
		Mint y(rr(rng)), xx(0), c(c_), ys(0), q(1);
		while(g == 1) {
			xx.n = y.n;
			for(uint i = 1; i <= r; i++)	y *= y, y += c;
			uint64_t k = 0; g = 1;
			while(k < r && g == 1) {
				for(uint i = 1; i <= (m > (r - k) ? (r - k) : m); i++) {
					ys.n = y.n;
					y *= y; y += c;
					uint64_t xxx = xx.val(), yyy = y.val();
					q *= Mint(xxx > yyy ? xxx - yyy : yyy - xxx);
				}
				g = __gcd<uint64_t>(q.val(), n);
				k += m;
			}
			r *= 2;
		}
		if(g == n)	g = 1;
		while(g == 1) {
			ys *= ys; ys += c;
			uint64_t xxx = xx.val(), yyy = ys.val();
			g = __gcd<uint64_t>(xxx > yyy ? xxx - yyy : yyy - xxx, n);
		}
		if(g != n && is_prime(g))	return g;
	}
	assert(69 == 420);
}

template <typename T>
vector<T> inter_factor(const T &n) {
	if(n < 2)	return { };
	if(is_prime(n))	return {n};
	T d = rho_pollard(static_cast<uint64_t>(n));
	vector<T> l = inter_factor(d), r = inter_factor(n / d);
	l.insert(l.end(), r.begin(), r.end());
	return l;
}

template <typename T>
vector<T> factor(T n) {
	vector<T> f1;
	for(uint i = 2; i < 100; i += (i & 1) + 1)
		while(n % i == 0)	f1.push_back(i), n /= i;
	vector<T> f2 = inter_factor(n);
	f1.insert(f1.end(), f2.begin(), f2.end());
	sort(f1.begin(), f1.end());
	return f1;
}


void solve(int n, int k, ll s) {
	vector<ll> x(n), y(n), z(n);
	rep(i,0,n) {
		cin >> x[i] >> y[i] >> z[i];
	}

	auto hyomen_sub = [&](ll ax, ll ay, ll bx, ll by) {
		ll xl = max(ax, bx);
		ll xr = min(ax + s, bx + s);
		ll yl = max(ay, by);
		ll yr = min(ay + s, by + s);
		ll xlen = max(0LL, xr - xl);
		ll ylen = max(0LL, yr - yl);
		return ylen * xlen * 2;
	};

	// common hyomen of (i, j)
	auto hyomen = [&](int i, int j) -> ll {
		// x[i], y[i], z[i];
		// x[j], y[j], z[j];
		ll ans = 0;
		ans += hyomen_sub(x[i], y[i], x[j], y[j]);
		ans += hyomen_sub(y[i], z[i], y[j], z[j]);
		ans += hyomen_sub(z[i], x[i], z[j], x[j]);
		return ans;
	};

	auto is_linked = [&](int i, int j) -> bool {
		if (hyomen_sub(x[i], y[i], x[j], y[j]) == 0) return false;
		if (hyomen_sub(y[i], z[i], y[j], z[j]) == 0) return false;
		if (hyomen_sub(z[i], x[i], z[j], x[j]) == 0) return false;
		return true;
	};

	vector ikeru(n, vector<int>(0));
	rep(i,0,n) {
		rep(j,i+1,n) {
			if (i == j) continue;
			if (is_linked(i, j)) {
				ikeru[i].push_back(j);
				ikeru[j].push_back(i);
			}
		}
	}

	atcoder::dsu uf(n);
	rep(i,0,n){
		for (int j: ikeru[i]) {
			uf.merge(i, j);
		}
	}
	
	vector<int> deg_sum(n);
	rep(i,0,n){
		deg_sum[uf.leader(i)] += (int)ikeru[i].size();
	}

	// minimum answer
	ll ans = 1e18;

	rep(st,0,n) {
		if (uf.leader(st) != st) continue;
		//cout << deg_sum[st] << ' ' << uf.size(st) << endl;
		if (deg_sum[st] == uf.size(st) * 2) {
			// circle;
			int genten = st;
			vector<int> renketsu_list;
			vector<bool> seen(n);
			seen[genten] = 1;
			
			vector<int> mada(0);
			mada.push_back(genten);
			while(!mada.empty()){
				int i = mada.back();
				mada.pop_back();
				renketsu_list.push_back(i);
				for (int j: ikeru[i]) {
					if (seen[j]) continue;
					mada.push_back(j);
					seen[j] = 1;
					break;
				}
			}
			
			int m = (int)renketsu_list.size();
			rep(i,0,m-1) {
				assert(is_linked(renketsu_list[i],renketsu_list[i+1]));
			}
			assert(is_linked(renketsu_list[m-1],renketsu_list[0]));
			//cout << m << endl;

			// unused with originally genten -> 0
			vector dp_sub0(2*m, vector<ll>(m+1, (ll)1e18));
			// used with originally genten -> 0
			vector dp_sub1(2*m, vector<ll>(m+1, (ll)1e18));
			vector dp_sub2(2*m, vector<ll>(m+1, (ll)1e18));
			dp_sub0[0][0] = 0;
			dp_sub1[0][1] = 6*s*s;
			rep(i,1,2*m) {
				rep(j,0,m+1) {
					chmin(dp_sub0[i][j], dp_sub0[i-1][j]);
					chmin(dp_sub2[i][j], dp_sub1[i-1][j]);
					chmin(dp_sub2[i][j], dp_sub2[i-1][j]);
				}
				rep(j,0,m) {
					chmin(dp_sub1[i][j+1], dp_sub0[i-1][j] + 6*s*s);
					chmin(dp_sub1[i][j+1], dp_sub1[i-1][j] + 6*s*s - hyomen(renketsu_list[(i-1)%m], renketsu_list[i%m]));
				}
			}
			ll val = 0;
			rep(i,0,m) {
				val += 6 * s * s;
				val -= hyomen(renketsu_list[i], renketsu_list[(i+1)%m]);
			}
			if (m==k) chmin(ans, val);
			if (m>k) {
				chmin(ans,dp_sub1[2*m-1][k]);
				chmin(ans,dp_sub2[2*m-1][k]);
				
			}
		}else if (deg_sum[st] == uf.size(st) * 2 - 2){
			if (deg_sum[st] == 0) {
				if (k == 1) {
					chmin(ans,6*s*s);
				}
				continue;
			}

			// path;
			int genten = -1;
			rep(i,0,n) {
				if (!uf.same(i,st)) continue;
				if ((int)ikeru[i].size() == 1) {
					genten = i;
					break;
				}
			}
			assert(genten != -1);
			
			vector<int> renketsu_list;
			vector<bool> seen(n);
			seen[genten] = 1;
			
			vector<int> mada(0);
			mada.push_back(genten);
			while(!mada.empty()){
				int i = mada.back();
				mada.pop_back();
				renketsu_list.push_back(i);
				for (int j: ikeru[i]) {
					if (seen[j]) continue;
					mada.push_back(j);
					seen[j] = 1;
				}
			}

			int m = (int)renketsu_list.size();
			// unused
			vector dp_sub0(m, vector<ll>(m+1, (ll)1e18));
			// used
			vector dp_sub1(m, vector<ll>(m+1, (ll)1e18));
			// end
			vector dp_sub2(m, vector<ll>(m+1, (ll)1e18));
			dp_sub0[0][0] = 0;
			dp_sub1[0][1] = 6 * s * s;
			rep(i,1,m) {
				rep(j,0,m+1) {
					chmin(dp_sub0[i][j], dp_sub0[i-1][j]);
					chmin(dp_sub2[i][j], dp_sub1[i-1][j]);
					chmin(dp_sub2[i][j], dp_sub2[i-1][j]);
				}
				rep(j,0,m) {
					chmin(dp_sub1[i][j+1], dp_sub0[i-1][j] + 6*s*s);
					chmin(dp_sub1[i][j+1], dp_sub1[i-1][j] + 6*s*s - hyomen(renketsu_list[i-1], renketsu_list[i]));
				}
			}
//			vector<ll> ret(m+1,(ll)1e18);
			if (m>=k) {
				chmin(ans,dp_sub1[m-1][k]);
				chmin(ans,dp_sub2[m-1][k]);
			}
			

		}else{
			assert(false);
		}
	}

	/*

	vector<ll> ans(1,0LL);

	for (auto a: gogo_list) {
		vector<ll> nans((int)a.size()+(int)ans.size()-1,(ll)1e18);
		rep(i,0,(int)a.size()) {
			rep(j,0,(int)ans.size()) {
				chmin(nans[i+j],a[i]+ans[j]);
			}
		}
		swap(ans,nans);
	}
		*/
	if (ans<1e17){
		cout<<ans<<endl;
	}else{
		cout<<-1<<endl;
	}
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	while(true) {
		int n; cin >> n;
		int k; cin >> k;
		ll s; cin >> s;
		if (n == 0) break;
		solve(n, k, s);
	}
}
accuracy: 1
time_ms: 10
memory_kb: 5376
final_rank: 15

code_snippet: # include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const double pi = acos(-1);
template<class T>constexpr T inf() { return ::std::numeric_limits<T>::max(); }
template<class T>constexpr T hinf() { return inf<T>() / 2; }
template <typename T_char>T_char TL(T_char cX) { return tolower(cX); }
template <typename T_char>T_char TU(T_char cX) { return toupper(cX); }
template<class T> bool chmin(T& a,T b) { if(a > b){a = b; return true;} return false; }
template<class T> bool chmax(T& a,T b) { if(a < b){a = b; return true;} return false; }
int popcnt(unsigned long long n) { int cnt = 0; for (int i = 0; i < 64; i++)if ((n >> i) & 1)cnt++; return cnt; }
int d_sum(ll n) { int ret = 0; while (n > 0) { ret += n % 10; n /= 10; }return ret; }
int d_cnt(ll n) { int ret = 0; while (n > 0) { ret++; n /= 10; }return ret; }
ll gcd(ll a, ll b) { if (b == 0)return a; return gcd(b, a%b); };
ll lcm(ll a, ll b) { ll g = gcd(a, b); return a / g*b; };
ll MOD(ll x, ll m){return (x%m+m)%m; }
ll FLOOR(ll x, ll m) {ll r = (x%m+m)%m; return (x-r)/m; }
template<class T> using dijk = priority_queue<T, vector<T>, greater<T>>;
# define all(qpqpq)           (qpqpq).begin(),(qpqpq).end()
# define UNIQUE(wpwpw)        (wpwpw).erase(unique(all((wpwpw))),(wpwpw).end())
# define LOWER(epepe)         transform(all((epepe)),(epepe).begin(),TL<char>)
# define UPPER(rprpr)         transform(all((rprpr)),(rprpr).begin(),TU<char>)
# define rep(i,upupu)         for(ll i = 0, i##_len = (upupu);(i) < (i##_len);(i)++)
# define reps(i,opopo)        for(ll i = 1, i##_len = (opopo);(i) <= (i##_len);(i)++)
# define len(x)                ((ll)(x).size())
# define bit(n)               (1LL << (n))
# define pb push_back
# define eb emplace_back
# define exists(c, e)         ((c).find(e) != (c).end())

struct INIT{
	INIT(){
		std::ios::sync_with_stdio(false);
		std::cin.tie(0);
		cout << fixed << setprecision(20);
	}
}INIT;

namespace mmrz {
	void solve();
}

int main(){
	mmrz::solve();
}
#define debug(...) (static_cast<void>(0))

using namespace mmrz;
#define rep2(i,a,n) for(int i=a;i<n;i++)
bool SOLVE(){
	ll n, k, s; cin >> n >> k >> s;
	if(n==0) return true;
	
	vector<tuple<ll,ll,ll>> v(n);
	rep(i,n) {
		ll x, y, z; cin >> x >> y >> z;
		v[i] = {x, y, z};
	}

	// auto calc_d = [&](ll l, ll r) -> ll {
	// 	ll ret = -1;
	// 	if(l > r)swap(l, r);
	// 	if(r <= l + s){
	// 		return l+s-r;
	// 	}
	// 	return ret;
	// };

	vector<vector<pair<ll,ll>>> g(n);
	rep(i,n) {
		auto [x1, y1, z1] = v[i];
		ll xs = x1 + s;
		ll ys = y1 + s;
		ll zs = z1 + s;
		rep2(j,i+1,n) {
			auto [x2,y2,z2] = v[j];
			bool isAlreadyChecked = false;
			rep(x_mul, 2) rep(y_mul, 2) rep(z_mul, 2) {
				if(isAlreadyChecked) break;
				ll px = x2 + s*x_mul;
				ll py = y2 + s*y_mul;
				ll pz = z2 + s*z_mul;
				if(x1 <= px && px <= xs && y1 <= py && py <= ys && z1 <= pz && pz <= zs) {
					isAlreadyChecked = true;
					ll dx = x_mul == 0 ? xs-px: px-x1;
					ll dy = y_mul == 0 ? ys-py: py-y1;
					ll dz = z_mul == 0 ? zs-pz: pz-z1;
					ll weight = 2ll*dx*dy + 2ll*dx*dz + 2ll*dy*dz;
					g[i].push_back({j, weight});
					g[j].push_back({i, weight});
				}
			}
		}
		// rep(j, n) {
		// // for(int j = i+1;j < n;j++) {
		// 	if(i == j)continue;
		// 	auto [x2, y2, z2] = v[j];

		// 	ll xs = x1 + s;
		// 	ll ys = y1 + s;
		// 	ll zs = z1 + s;

		// 	// ll dx = calc_d(x1, x2);
		// 	// ll dy = calc_d(y1, y2);
		// 	// ll dz = calc_d(z1, z2);

		// 	// if(dx == -1 || dy == -1 || dz == -1)continue;

		// 	// ll weight = 2ll*dx*dy + 2ll*dx*dz + 2ll*dy*dz;

		// 	// g[i].push_back({j,weight});
		// 	// g[j].push_back({i,weight});
			
		// 	if(x1 <= x2 && x2 <= xs && y1 <= y2 && y2 <= ys && z1 <= z2 && z2 <= zs) {

		// 		ll dx = xs - x2;
		// 		ll dy = ys - y2;
		// 		ll dz = zs - z2;

		// 		ll weight = 2ll*dx*dy + 2ll*dx*dz + 2ll*dy*dz;

		// 		g[i].push_back({j,weight});
		// 		g[j].push_back({i,weight});
			
		// 	}
		// }
	}

	debug(g);

	if(k == 1){
		cout << 6ll*s*s << '\n';
		return 0;
	}
	
	if(k == 2){
		ll ans = hinf<ll>();
		rep(i, n){
			for(auto [to, e] : g[i]){
				chmin(ans, 6ll*s*s*2 - e);
			}
		}
		cout << (ans == hinf<ll>() ? -1 : ans) << '\n';
		return 0;
	}

	debug(g);
	ll ans = hinf<ll>();
	
	rep(i, n){
		for(auto [TO, E] : g[i]){
			ll sm = E;
			unordered_set<int> st;
			st.emplace(i);
			st.emplace(TO);
			int cur = TO, pre = i;
			bool flg = true;
			for(int rem = k-2;rem >= 0;rem--){
				
				bool update = false;
				for(auto [to, e] : g[cur]){
					if(to == pre)continue;
					if(rem != 0 && st.contains(to))continue;
					if(rem != 0 || st.contains(to))sm += e;
					st.emplace(to);
					pre = cur;
					cur = to;
					update = true;
					break;
				}
				debug(pre, cur, sm, rem, st, update);
				if(rem && not update){
					flg = false;
					break;
				}
			}
			if(flg){
				chmin(ans, 6ll*s*s*k - sm);
				debug(st, sm);
			}
		}
	}
	cout << (ans == hinf<ll>() ? -1 : ans) << '\n';
	return 0;
}

void mmrz::solve(){
	// int t = 1;
	//cin >> t;
	while(!SOLVE());
}
accuracy: 1
time_ms: 20
memory_kb: 3584
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;

bool connect(vector<int> v1, vector<int> v2, int S){
    if(abs(v1[0]-v2[0])<S&&abs(v1[1]-v2[1])<S&&abs(v1[2]-v2[2])<S) return true;
    else return false;
}

int add(vector<int> v1, vector<int> v2, int S){
    vector<int> dr(3);
    for(int i=0;i<3;i++) dr[i]=S-abs(v1[i]-v2[i]);
    int ret=6*S*S-2*(dr[0]*dr[1]+dr[1]*dr[2]+dr[2]*dr[0]);
    return ret;
}

int epoint(int s,vector<vector<int>> &side){
    set<int> itta;
    queue<vector<int>> que;
    int last=s;
    que.push({s,-1});//{今の位置,前の位置}
    itta.insert(s);
    while(!que.empty()){
        auto v=que.front();
        que.pop();
        int now=v[0],pre=v[1];
        for(int next:side[now]){
            if(next==pre) continue;
            if(itta.count(next)){
                last=-1;
                break;
            }
            else{
                itta.insert(next);
                last=next;
                que.push({next,now});
            }
        }
        if(last==-1) break;
    }
    return last;
}


void solve(int N, int K, int S,vector<int> &ANS){
    
    vector<vector<int>> pos(N,vector<int>(3));
    for(int i=0;i<N;i++){
        for(int j=0;j<3;j++){
            cin >> pos[i][j];
        }
    }
    if(K==1){
        ANS.push_back(6*S*S);
        return;
    }
    vector<vector<int>> side(N,vector<int>(0));
    for(int i=0;i<N;i++){
        for(int j=i+1;j<N;j++){
            if(connect(pos[i],pos[j],S)){
                side[i].push_back(j);
                side[j].push_back(i);
                //cout << i<<"と"<<j<<"は連結"<<endl;//
            }
        }
    }
    vector<bool> used(N,false);
    int ans=INT_MAX;
    for(int i=0;i<N;i++){
        if(!used[i]){
            int start=epoint(i,side);
            if(start==-1){
                vector<int> con;
                con.push_back(i);
                used[i]=true;
                int sec=side[i][0];
                con.push_back(sec);
                used[sec]=true;

                queue<int> hai;
                hai.push(sec);
                while(!hai.empty()){
                    int now=hai.front();
                    hai.pop();
                    for(int next:side[now]){
                        if(!used[next]){
                            used[next]=true;
                            con.push_back(next);
                            hai.push(next);
                        }
                    } 
                }
                int sz=con.size();
                if(sz==K){
                    int area=0;
                    for(int j=0;j<K;j++){
                        area+=add(pos[con[j]],pos[con[(j+1)%K]],S);
                    }
                    ans=min(ans,area);
                }
                if(sz>K){
                    int area=6*S*S;
                    for(int j=1;j<K;j++){
                        area+=add(pos[con[j-1]],pos[con[j]],S);
                    }
                    ans=min(ans,area);
                    //cout << "ループの場合"<<area<<endl;//
                    for(int j=1;j<sz;j++){
                        area+=add(pos[con[(K-2+j)%sz]],pos[con[(K-1+j)%sz]],S);
                        area-=add(pos[con[j-1]],pos[con[j]],S);
                        ans=min(ans,area);
                        //cout << "ループの場合"<<area<<endl;//
                    }
                }
            }
            else{
                queue<int> hai;
                hai.push(start);
                used[start]=true;
                vector<int> con;
                con.push_back(start);
                while(!hai.empty()){
                    int now=hai.front();
                    hai.pop();
                    for(int next:side[now]){
                        if(!used[next]){
                            used[next]=true;
                            con.push_back(next);
                            hai.push(next);
                        }
                    } 
                }
                int sz=con.size();
                //for(int x:con) cout << x <<' ';//
                //cout <<"これらは連結"<<endl;//
                if(sz>=K){
                    int area=6*S*S;
                    for(int j=1;j<K;j++){
                        area+=add(pos[con[j-1]],pos[con[j]],S);
                    }
                    ans=min(ans,area);
                    //cout << "鎖状の場合"<<area<<endl;//
                    for(int j=K;j<sz;j++){
                        area+=add(pos[con[j-1]],pos[con[j]],S);
                        area-=add(pos[con[j-K]],pos[con[j-K+1]],S);
                        ans=min(ans,area);
                        //cout << "鎖状の場合"<<area<<endl;//
                    }
                }
            }
        }
    }
    if(ans==INT_MAX) ans=-1;
    ANS.push_back(ans);

}



int main() {
    vector<int> ANS;
    while(true){
        int N,K,S;
        cin>>N>>K>>S;
        if(N==0) break;
        solve(N,K,S,ANS);
    }
    for(int a:ANS) cout << a << endl;
    
}
accuracy: 1
time_ms: 20
memory_kb: 3432
final_rank: 10

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

bool solve() {
    long long N, K, S;
    std::cin >> N >> K >> S;
    if (N == 0) return false;
    std::array<std::vector<long long>, 3> P;
    for (int i{} ; i < 3 ; i++) P[i] = std::vector<long long>(N);
    for (int i{} ; i < N ; i++) {
        for (int j{} ; j < 3 ; j++) std::cin >> P[j][i];
    }
    std::vector<std::vector<std::pair<int, long long>>> g(N);
    for (int i{} ; i < N ; i++) {
        for (int j{} ; j < N ; j++) {
            if (i == j) continue;
            bool ok{true};
            long long len[3];
            for (int k{} ; k < 3 ; k++) {
                long long l{std::max(P[k][i], P[k][j])}, r{std::min(P[k][i], P[k][j]) + S};
                ok &= (l < r);
                len[k] = r - l;
            }
            if (!ok) continue;
            long long cost{};        
            for (int i{} ; i < 3 ; i++) {
                long long area{len[i + 1 == 3 ? 0 : i + 1] * len[i]};
                cost += 2 * area;
            }
            g[i].emplace_back(j, cost);
        }
    }
    std::vector<bool> used(N);
    int start{-1};
    auto rec{[&](auto rec, int v, int cnt, long long sum) -> long long {
        long long res{(cnt == K ? sum : -1)};
        for (auto [x, w] : g[v]) {
            if (!used[x] and cnt < K) {
                used[x] = true;
                res = std::max(res, rec(rec, x, cnt + 1, sum + w));
                used[x] = false;
            }
            else if (K != 2 and cnt == K and x == start) {
                assert(used[x]);
                res += w;
            }
        }
        return res;
    }};
    long long ans{-1};
    for (int v{} ; v < N ; v++) {
        used[v] = true;
        start = v;
        ans = std::max(ans, rec(rec, v, 1, 0LL)); 
        used[v] = false;
    }
    if (ans == -1) {
        std::cout << ans << '\n';
    }
    else {
        ans = (long long)K * 6 * S * S - ans;
        std::cout << ans << '\n';
    }
    return true;
}

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    while (solve()) ;
}
accuracy: 1
time_ms: 20
memory_kb: 3456
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define ALL(v) v.begin(),v.end()
template<class F, class S>
ostream& operator<<(ostream& os, const pair<F,S>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template<class Iter>
void print(Iter begin, Iter end) {
    for (auto itr = begin; itr != end; ++itr) {
        cerr << (*itr) << ' ';
    }
    cerr << '\n';
}
#define dbg(v) cerr << #v << ": " << v << '\n';
int N,K,S;
vector<array<int,3>> P;
using Graph = vector<vector<int>>;
Graph G;
vector<vector<int>> W;

int cycle(vector<int>& vert) {
    if (vert.size() == K) {
        int sum = 0;
        for (int i : vert) {
            for (int j : vert) {
                sum += W[i][j];
            }
        }
        assert(sum % 2 == 0);
        return sum / 2;
    }
    int n = vert.size();
    map<int, bool> used;
    int start = vert[0];
    vert.clear();
    vert.push_back(start);
    used[start] = true;
    for (int i = 0; i < n-1; ++i) {
        int pos = vert.back();
        for (int to : G[pos]) {
            if (!used[to]) {
                vert.push_back(to);
                used[to] = true;
                break;
            }
        }
    }
    for (int i = 0; i < n; ++i) {
        vert.push_back(vert[i]);
    }

    vector<int> rui(2*n);
    for (int i = 1; i < 2*n; ++i) {
        rui[i] = rui[i-1] + W[vert[i]][vert[i-1]];
    }
    int res = 0;
    for (int i = K-1; i < 2*n; ++i) {
        res = max(res, rui[i] - rui[i-K+1]);
    }
    return res;
}

int path(vector<int>& vert) {
    int start = -1;
    for (int v : vert) {
        if (G[v].size() <= 1) {
            start = v;
            break;
        }
    }
    int n = vert.size();
    map<int, bool> used;
    vert.clear();
    vert.push_back(start);
    used[start] = true;
    for (int i = 0; i < n-1; ++i) {
        int pos = vert.back();
        for (int to : G[pos]) {
            if (!used[to]) {
                vert.push_back(to);
                used[to] = true;
                break;
            }
        }
    }

    vector<int> rui(n);
    for (int i = 1; i < n; ++i) {
        rui[i] = rui[i-1] + W[vert[i]][vert[i-1]];
    }
    int res = 0;
    for (int i = K-1; i < n; ++i) {
        res = max(res, rui[i] - rui[i-K+1]);
    }
    return res;
}

int calc(int x1, int y1, int z1, int x2, int y2, int z2)
{
    if (x1 > x2) swap(x1, x2);
    int dx = max(0, x1 + S - x2);
    if (y1 > y2) swap(y1, y2);
    int dy = max(0, y1 + S - y2);
    if (z1 > z2) swap(z1, z2);
    int dz = max(0, z1 + S - z2);
    if (dx==0 || dy==0 || dz==0) return 0;
    return (dx * dy + dy * dz + dz * dx) * 2;
}

int solve() {
    cin >> N >> K >> S;
    if (N+K+S == 0) exit(0);
    P.resize(N);
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < 3; ++j) {
            cin >> P[i][j];
        }
    }

    G.clear();
    G.resize(N);
    W.clear();
    W.resize(N, vector<int>(N,0));
    for (int i = 0; i < N; ++i) {
        for (int j = i+1; j < N; ++j) {
            // calc weight of edge i-j
            auto [x1, y1, z1] = P[i];
            auto [x2, y2, z2] = P[j];
            int diff = calc(x1,y1,z1, x2,y2,z2);
            W[i][j] = W[j][i] = diff;
            if (diff > 0) {
                G[i].emplace_back(j);
                G[j].emplace_back(i);
            }
        }
    }
    // for (int i = 0; i < N; ++i) {
    //     cerr << i << ":";
    //     print(ALL(G[i]));
    // }
    vector<bool> used(N);
    int ans = -1;
    for (int i = 0; i < N; ++i) {
        if (used[i]) continue;
        vector<int> vert;
        queue<int> q;
        used[i] = true;
        q.push(i);
        vert.push_back(i);
        while (q.size()) {
            int v = q.front();
            q.pop();
            for (auto to : G[v]) {
                if (!used[to]) {
                    used[to] = true;
                    q.push(to);
                    vert.push_back(to);
                }
            }
        }

        bool isCycle = true;
        for (int v : vert) {
            if (G[v].size() != 2) {
                isCycle = false;
            }
        }
        if (vert.size() < K) {continue;}

        if (isCycle) {
            ans = max(ans, cycle(vert));
        } else {
            ans = max(ans, path(vert));
        }
    }
    if (ans == -1) return -1;
    return K * S*S*6 - ans;
}

int main() {
    while (true) {
        cout << solve() << '\n';
    }
}
accuracy: 1
time_ms: 10
memory_kb: 7000
final_rank: 19

code_snippet: #include "bits/stdc++.h"

using namespace std;

using i64 = long long;
using ll = long long;

bool solve(){
    int n, k, s;
    cin >> n >> k >> s;
    if (n == 0) {
        return false;
    }
    vector<ll> x(n);
    vector<ll> y(n);
    vector<ll> z(n);
    for (int i = 0; i < n; i++) {
        cin >> x[i] >> y[i] >> z[i];
    }
    ll base = s * s * 6 * k;
    if (k == 1) {
        cout << base << endl;
        return true;
    }
    vector<int> e1(n, -1);
    vector<int> e2(n, -1);
    vector<ll> s1(n, -1);
    vector<ll> s2(n, -1);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j) {
                continue;
            }
            ll ix = s + min(x[i], x[j]) - max(x[i], x[j]);
            ll iy = s + min(y[i], y[j]) - max(y[i], y[j]);
            ll iz = s + min(z[i], z[j]) - max(z[i], z[j]);
            if (ix > 0 && iy > 0 && iz > 0) {
                ll siz = (ix * iy + ix * iz + iy * iz) * 2;
                if (e1[i] == -1) {
                    e1[i] = j;
                    s1[i] = siz;
                } else {
                    e2[i] = j;
                    s2[i] = siz;
                }
            }
        }
    }
    ll ans = 0;
    bool any = false;
    for (int i = 0; i < n; i++) {
        if (e1[i] != -1) {
            int p = i;
            int c = e1[i];
            ll su = 0;
            ll ns = s1[i];
            bool ok = true;
            //cout << i << "_2" << endl;
            for (int j = 1; j < k; j++) {
                //cout << c << ", " << p << endl;
                if (c == -1) {
                    ok = false;
                    break;
                }
                su += ns;
                if (e1[c] == p && e2[c] != -1) {
                    ns = s2[c];
                    p = c;
                    c = e2[c];
                } else if (e2[c] == p && e1[c] != -1) {
                    ns = s1[c];
                    p = c;
                    c = e1[c];
                } else {
                    p = c;
                    c = -1;
                }
                if (p == i) {
                    ok = false;
                    break;
                }
            }
            if (c == i) {
                su += ns;
            }
            if (ok) {
                any = true;
                ans = max(ans, su);
            }
        }
        if (e2[i] != -1) {
            int p = i;
            int c = e2[i];
            ll su = 0;
            ll ns = s2[i];
            bool ok = true;
            //cout << i << "_2" << endl;
            for (int j = 1; j < k; j++) {
                //cout << c << ", " << p << endl;
                if (c == -1) {
                    ok = false;
                    break;
                }
                su += ns;
                if (e1[c] == p && e2[c] != -1) {
                    ns = s2[c];
                    p = c;
                    c = e2[c];
                } else if (e2[c] == p && e1[c] != -1) {
                    ns = s1[c];
                    p = c;
                    c = e1[c];
                } else {
                    p = c;
                    c = -1;
                }
                if (p == i) {
                    ok = false;
                    break;
                }
            }
            if (c == i) {
                su += ns;
            }
            if (ok) {
                any = true;
                ans = max(ans, su);
            }
        }
    }
    if (any) {
        cout << base - ans << endl;
    } else {
        cout << -1 << endl;
    }
    return true;
}

int main() {
    while(solve());
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3432
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;


struct Unionfind{
private:
    int n;
    std::vector<int> parents;

public:
    Unionfind(int n):n(n), parents(n,-1) {}

    int find(int x) {
        if(parents[x] < 0) return x;
        return parents[x] = find(parents[x]);
    }

    void unite(int x,int y) {
        x = find(x);
        y = find(y);

        if(x == y) return;
        if(parents[x] > parents[y]) std::swap(x, y);
        parents[x] += parents[y];
        parents[y] = x;
        return;
    }  

    int size(int x) {
        return -parents[find(x)];
    }

    bool same(int x, int y) {
        return find(x) == find(y);
    }

    std::vector<int> members(int x) {
        int root = find(x);
        std::vector<int> member;
        for(int i = 0;i < n; i++){
            if(find(i) == root ){
                member.push_back(i);
            }
        }
        return member;
    }

    int group_cnt(void) {
        int c = 0;
        for(int i = 0;i < n; i++){
            if(parents[i] < 0) ++c;
        }
        return c;
    }
};

long long calc(vector<vector<pair<int,long long>>>& G, Unionfind& uf, vector<bool> in_circle, int n, int k, int s){
    long long ans = -1;
    vector<bool> done(G.size());
    for(int i = 0; i < G.size(); i++){
        if(done[i]) continue;
        auto member = uf.members(i);
        if(member.size() < k) continue;


        bool circle = false;
        int start = i;
        for(int j = 0; j < member.size(); j++){
            int m = member[j];
            done[m] = 1, circle |= in_circle[m];
            if(G[m].size() == 1) start = m;
        }

      //  cout << circle << endl;
       // for(int i = 0; i < member.size(); i++) cout << member[i] << " ";
        //cout << endl;

        vector<long long> a;
        vector<bool> visited(member.size());
        auto dfs = [&](auto&& self, int v, int prev = -1)->void{
            visited[v] = true;
            for(auto[nv, rew] : G[v]){
                if(visited[nv]){
                    if(prev != start && nv == start) a.push_back(rew);
                    continue;
                }
                a.push_back(rew);
                self(self, nv, v);
            }
        };
        dfs(dfs, start);

        //for(int i = 0; i < a.size(); i++){
          //   cout << a[i] << " ";
        //}
        //cout << endl;

        if(member.size() == k){
            ans = max(ans, accumulate(a.begin(), a.end(), 0ll));
        }
        else{
            if(circle){
                vector<long long> sum(3*a.size() + 1);
                for(int i = 0; i < sum.size() - 1; i++){
                    sum[i + 1] = sum[i] + a[i % a.size()];
                }
                for(int i = k - 1; i <= a.size() + k; i++){
                    ans = max(ans, sum[i] - sum[i - (k - 1)]);
                }
            }
            else{
                vector<long long> sum(a.size() + 1);
                for(int i = 0; i < a.size(); i++){
                    sum[i + 1] = sum[i] + a[i % a.size()];
                }
                for(int i = k - 1; i < sum.size(); i++){
                    ans = max(ans, sum[i] - sum[i - (k - 1)]);
                }
            }
        }
    }
    return ans;
}   


void solve(int n, int k, long long s){
    vector<int> x(n), y(n), z(n);
    Unionfind uf(n);
    vector<bool> in_circle(n);
    vector<vector<pair<int, long long>>> G(n);
    for(int i = 0; i < n; i++) cin >> x[i] >> y[i] >> z[i];
    auto process = [&](int i, int j)->void{
        long long area = 0;
        for(int mask = 0; mask < 1<<3; mask++){
            vector<int> co(3);
            co[0] = x[i], co[1] = y[i], co[2] = z[i];
            for(int p = 0; p < 3; p++){
                if(mask >> p & 1) co[p] += s;
            }
            if(x[j] <= co[0] && co[0] <= x[j] + s && y[j] <= co[1] && co[1] <= y[j] + s && z[j] <= co[2] && co[2] <= z[j] + s){
                long long tate = ((mask >> 0 & 1) ? co[0] - x[j] : x[j] + s - co[0]);
                long long yoko = ((mask >> 1 & 1) ? co[1] - y[j] : y[j] + s - co[1]);
                long long takasa = ((mask >> 2 & 1) ? co[2] - z[j] : z[j] + s - co[2]);
                area = 2 * (tate * yoko + tate * takasa + yoko * takasa);
            }   
        }
        if(area != 0){
            G[i].push_back({j, area}), G[j].push_back({i, area});
            if(uf.same(i, j)) in_circle[i] = in_circle[j] = 1;
            uf.unite(i, j);
        }
    };
    for(int i = 0; i < n; i++) for(int j = 0; j < i; j++) process(i, j);
    //for(int i = 0; i < n; i++){
    //    for(auto[j, cost]:G[i]) cout << i << " " << j << " " << cost << endl;
    //}
    long long tmp =  calc(G, uf, in_circle, n, k, s);
    if(tmp == -1) cout << tmp << endl;
    else cout << 6*s*s*k - tmp << endl;
}

int main() {
    while(1){
        int n, k, s; cin >> n >> k >> s;
        if(n == 0 && k == 0 && s == 0) break;
        solve(n, k, s);
    }
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3544
final_rank: 17

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

#define rep(i,s,n) for (int i = s; i < (int)(n); i++)
#define rrep(i,s,n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) v.begin(),v.end()

using ll = long long;
using ull = unsigned long long;

template<typename T> bool chmin(T &a, const T &b){
    if (a <= b) return false;
    a = b;
    return true;
}
template<typename T> bool chmax(T &a, const T &b){
    if (a >= b) return false;
    a = b;
    return true;
}

int main() {
    const int INF = std::numeric_limits<int>::max();
    int n,k,s;
    while(std::cin >> n >> k >> s, n != 0) {
        using P = std::array<int, 3>;
        std::vector<P> ps(n);
        for(auto &p: ps) {
            rep(i,0,3) {
                std::cin >> p[i];
            }
        }
        auto is_connect = [&](P a, P b) -> bool {
            rep(bit,0,1<<3) {
                bool is_ok = true;
                rep(i,0,3) {
                    int ret = a[i];
                    if((bit >> i) & 1) {
                        ret += s;
                    }
                    is_ok &= b[i] <= ret && ret <= b[i] + s;
                }
                if(is_ok) return true;
            }
            return false;
        };
        auto f = [&](P a, P b) -> int {
            P diff;
            rep(i,0,3) diff[i] = s - std::abs(a[i] - b[i]);
            int ret = 0;
            rep(i,0,3) ret += 2 * diff[i] * diff[(i + 1) % 3];
            return ret;
        };
        if(k == 1) {
            std::cout << 6 * s * s << '\n';
            continue;
        }
        if(k == 2) {
            int ans = INF;
            rep(i,0,n) {
                rep(j,i+1,n) {
                    if(is_connect(ps[i], ps[j])) chmin(ans, 6*s*s*2 - f(ps[i], ps[j]));
                }
            }
            if(ans == INF) ans = -1;
            std::cout << ans << '\n';
            continue;
        }

        std::vector g(n, std::vector<int>());
        rep(i,0,n) rep(j,i+1,n) {
            if(is_connect(ps[i], ps[j])) {
                g[i].emplace_back(j);
                g[j].emplace_back(i);
            }
        }
        std::vector<std::vector<int>> groups;
        {
            std::vector<int> deg1;
            std::vector<int> seen(n, -1);
            std::vector<int> group;
            auto dfs = [&](auto &&self, int v) -> void {
                seen[v] = 1;
                group.emplace_back(v);
                for(auto nv: g[v]) if(seen[nv] < 0) {
                    self(self, nv);
                }
            };
            rep(i,0,n) if(g[i].size() == 1 && seen[i] < 0) {
                dfs(dfs, i);
                groups.emplace_back(group);
                group.clear();
            }
            rep(i,0,n) if(seen[i] < 0) {
                dfs(dfs, i);
                groups.emplace_back(group);
                group.clear();
            }
        }
        int ans = INF;
        for(auto group: groups) {
            int sz = group.size();
            if(sz < k) continue;
            std::vector<int> diffs;
            rep(i,0,sz-1) {
                int idx = group[i];
                int jdx = group[i+1];
                diffs.emplace_back(f(ps[idx], ps[jdx]));
            }
            bool is_loop = is_connect(ps[group[0]], ps[group.back()]);
            int w = k-1;
            if(is_loop) {
                diffs.emplace_back(f(ps[group[0]], ps[group.back()]));
                if(sz == k) w = k;
            }
            sz = diffs.size();
            int ret = 0;
            rep(i,0,w) {
                ret += diffs[i];
            }
            chmin(ans, 6 * s * s * k - ret);
            rep(i,0,sz) {
                if(!is_loop && i + w >= sz) break;
                ret -= diffs[i];
                ret += diffs[(i + w) % sz];
                chmin(ans, 6 * s * s * k - ret);
            }
        }
        if(ans == INF) ans = -1;
        std::cout << ans << '\n';
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3572
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;

bool is_connect(int i, int j, int s, vector<int>&x, vector<int>&y, vector<int>&z){
	int px,py,pz,qx,qy,qz;
	for (int k=0; k<8; k++){
		if (k&1){
			px=i;
			qx=j;
		}else{
			px=j;
			qx=i;
		}
		if (k&2){
			py=i;
			qy=j;
		}else{
			py=j;
			qy=i;
		}
		if (k&4){
			pz=i;
			qz=j;
		}else{
			pz=j;
			qz=i;
		}
		if (!(x[px] <= x[qx] && x[qx] <= x[px]+s)) continue;
		if (!(y[py] <= y[qy] && y[qy] <= y[py]+s)) continue;
		if (!(z[pz] <= z[qz] && z[qz] <= z[pz]+s)) continue;
		return true;
	}
	return false;
}

int kasane(int i, int j, int s, vector<int>&x, vector<int>&y, vector<int>&z){
	int px,py,pz;
	if (x[i] <= x[j]){
		px = x[i]+s-x[j];
	}else{
		px = x[j]+s-x[i];
	}
	if (y[i] <= y[j]){
		py = y[i]+s-y[j];
	}else{
		py = y[j]+s-y[i];
	}
	if (z[i] <= z[j]){
		pz = z[i]+s-z[j];
	}else{
		pz = z[j]+s-z[i];
	}
	return 2*(px*py+py*pz+pz*px);
}

void solve(int n, int k, int s){
	vector<int> x(n), y(n), z(n);
	for (int i=0; i<n; i++){
		cin >> x[i] >> y[i] >> z[i];
	}

	vector<vector<int>> ikeru(n, vector<int>(0));
	vector<int> deg(n);
	for (int i=0; i<n; i++){
		for (int j=i+1; j<n; j++){
			if (is_connect(i, j, s, x, y, z)){
				ikeru[i].push_back(j);
				ikeru[j].push_back(i);
				deg[i] += 1;
				deg[j] += 1;
			}
		}
	}
	
	vector<int> deg1(0);
	vector<bool> tansaku(n);
	for (int i=0; i<n; i++){
		if (deg[i] <= 1) deg1.push_back(i);
	}
	vector<vector<int>> groups(0,vector<int>(0));
	int cnt = 0;
	vector<bool> isen(0);
	for (int st: deg1){
		vector<int> mada = {st};
		tansaku[st] = true;
		groups.push_back(vector<int>(0));
		groups[cnt].push_back(st);
		isen.push_back(false);
		while(!mada.empty()){
			int i = mada.back(); mada.pop_back();
			for (int j: ikeru[i]){
				if(!tansaku[j]){
					tansaku[j] = true;
					groups[cnt].push_back(j);
					mada.push_back(j);
				}
			}
		}
		cnt += 1;
	}
	for (int st=0; st<n; st++){
		if (tansaku[st]) continue;
		vector<int> mada = {st};
		groups.push_back(vector<int>(0));
		isen.push_back(true);
		while(!mada.empty()){
			int i = mada.back(); mada.pop_back();
			if(tansaku[i]) continue;
			groups[cnt].push_back(i);
			tansaku[i] = true;
			for (int j: ikeru[i]){
				if(!tansaku[j]){
					mada.push_back(j);
				}
			}
		}
		cnt += 1;
	}

	int ans = 1e9;
	for (int xx=0; xx<cnt; xx++){
		int m = groups[xx].size();
		if (m < k) continue;	
		int w = k-1;
		if (isen[xx]){
			if (m==k) w=k;
			vector<int> dif(2*m);
			for (int i=0; i<2*m; i++){
				dif[i] = kasane(groups[xx][i%m], groups[xx][(i+1)%m], s, x, y, z);
			}
			vector<int> rui(2*m+1);
			for (int i=0; i<2*m; i++){
				rui[i+1] = rui[i] + dif[i];
			}
			for (int i=0; i<=2*m-w; i++){
				ans = min(ans, 6*s*s*k - (rui[i+w] - rui[i]));
			}
		}else{
			vector<int> dif(m-1);
			for (int i=0; i<m-1; i++){
				dif[i] = kasane(groups[xx][i%m], groups[xx][(i+1)%m], s, x, y, z);
			}
			vector<int> rui(m);
			for (int i=0; i<m-1; i++){
				rui[i+1] = rui[i] + dif[i];
			}
			for (int i=0; i<m-w; i++){
				ans = min(ans, 6*s*s*k - (rui[i+w] - rui[i]));
			}
		}
	}
	if (ans == 1e9) ans = -1;
	cout << ans << "\n";
}

int main(){
	while(true){
		int n,k,s; cin >> n >> k >> s;
		if (n == 0) break;
		solve(n,k,s);
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3572
final_rank: 9

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

using namespace std;

#define rep(i,x,n) for(int i = (int)x; i < (int)n; i++)
#define rrep(i,x,n) for(int i = int(n) - 1; i >= x; i--)
#define all(a) a.begin(), a.end()

using ll = long long;
using ull = unsigned long long;

template<class T>
bool chmin(T &a, T b) {
    if(a <= b) return false;
    a = b;
    return true;
}

template<class T>
bool chmax(T &a, T b) {
    if(a >= b) return false;
    a = b;
    return true;
}

int main() {
    using pv = array<ll,3>;
    auto cnct = [](pv a, pv b, ll w){
        rep(s,0,8){
            pv c = {0,0,0};
            rep(i,0,3) c[i] = b[i] + (s >> i & 1) * w;
            bool ok = true;
            rep(i,0,3){
                if (c[i] < a[i] || a[i]+w < c[i]) ok = false;
            }
            if (ok) return true;
        }
        return false;
    };
    auto cov = [&](pv a, pv b, ll w){
        pv c = {0,0,0};
        rep(i,0,3) c[i] = w - abs(a[i]-b[i]);
        ll res = 0;
        rep(i,0,3){
            res += 2 * c[i] * c[(i+1)%3];
        }
        return res;
    };
    while (true){
        int n, k; cin >> n >> k;
        ll s; cin >> s;
        if (n == 0) break;
        vector<pv> a(n);
        rep(i,0,n){
            ll x, y, z; cin >> x >> y >> z;
            a[i] = {x,y,z};
        }
        if (k == 1){
            cout << 6*s*s << endl;
            continue;
        }
        if (k == 2){
            set<pv> st;
            bool ok = false;
            rep(i,0,n){
                if (st.find(a[i]) == st.end()){
                    st.insert(a[i]);
                }
                else {
                    ok = true; 
                }
            }
            if (ok){
                cout << 6*s*s << endl;
                continue;
            }
        }
        vector<vector<int>> es(n);
        vector<int> deg(n,0);
        rep(i,0,n) rep(j,0,n){
            if (i == j) continue;
            if (cnct(a[i],a[j],s)) es[i].emplace_back(j), deg[i]++;
        }
        vector<int> vis(n,0);
        const ll inf = 1'000'000'000'000'000'000;
        ll ans = inf;
        rep(i,0,n){
            if (vis[i] == 1) continue;
            vector<int> ids;
            ids.emplace_back(i);
            vis[i] = 1;
            queue<int> que;
            que.push(i);
            while (!que.empty()){
                int p = que.front(); que.pop(); //cout << p << endl;
                for (int q : es[p]){
                    if (vis[q] == 1) continue;
                    vis[q] = 1;
                    ids.emplace_back(q);
                    que.push(q);
                }
            }
            int nsiz = ids.size(); //cout << nsiz << endl; cout << endl;
            if (nsiz < k) continue;
            bool ng = true;
            int id = ids[0];
            for (int j : ids){
                if (deg[j] == 1) id = j, ng = false;
            }
            for (int j : ids) vis[j] = 0;
            ids.clear();
            ids.emplace_back(id);
            vis[id] = 1;
            que.push(id);
            while (!que.empty()){
                int p = que.front(); que.pop();
                for (int q : es[p]){
                    if (vis[q] == 1) continue;
                    vis[q] = 1;
                    ids.emplace_back(q);
                    que.push(q);
                    break;
                }
            }
            int siz = ids.size(); //cout << nsiz << endl;
            if (siz < k) continue;
            int cs = k-1;
            if (ng){
                if (siz == k){
                    ll cur = 6*s*s*k;
                    rep(j,0,siz) cur -= cov(a[ids[j]],a[ids[(j+1)%siz]],s);
                    if (k == 2) cur += cov(a[ids[0]],a[ids[1]],s);
                    chmin(ans,cur);
                    continue;
                }
                rep(j,0,siz){
                    ids.emplace_back(ids[j]);
                }
            }
            siz = ids.size();
            vector<ll> cum(siz, 0);
            rep(j,0,siz-1) {
                cum[j+1] = cum[j] + cov(a[ids[j]],a[ids[j+1]],s);
            }
            rep(j,0,siz) {
                if(j + cs >= siz) break;
                chmin(ans, 6*s*s*k - (cum[j+cs] - cum[j]));
            }
        }
        if (ans == inf) ans = -1;
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 60
memory_kb: 3432
final_rank: 14

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

using namespace std;

#define rep(i,x,n) for(int i = (int)x; i < (int)n; i++)
#define rrep(i,x,n) for(int i = int(n) - 1; i >= x; i--)
#define all(a) a.begin(), a.end()

using ll = long long;
using ull = unsigned long long;

template<class T>
bool chmin(T &a, T b) {
    if(a <= b) return false;
    a = b;
    return true;
}

template<class T>
bool chmax(T &a, T b) {
    if(a >= b) return false;
    a = b;
    return true;
}

const ll inf = ll(1) << ll(60);

int main() {
    ll n,k,s;
    using P = std::vector<ll>;
    while(std::cin >> n >> k >> s, !(n == 0)) {
        auto is_connect = [&](P a, P b){
            ll w = s;
            rep(ss,0,8){
                P c = {0,0,0};
                rep(i,0,3) c[i] = b[i] + (ss >> i & 1) * w;
                bool ok = true;
                rep(i,0,3){
                    if (c[i] < a[i] || a[i]+w < c[i]) ok = false;
                }
                if (ok) return true;
            }
            return false;
        };
        auto cover_sum = [&](P a, P b) -> ll {
            std::vector<ll> diff(3);
            rep(i,0,3) {
                ll x1 = a[i];
                ll x2 = b[i];
                if(x1 > x2) std::swap(x1, x2);
                diff[i] = x1 + s - x2;
            }
            ll sum = 0;
            rep(i,0,3) sum += 2 * diff[i] * diff[(i + 1) % 3];
            return sum;
        };
        std::vector<P> ps(n, P(3));
        for(auto &p: ps) {
            rep(i,0,3) std::cin >> p[i];
        }
        if(k == 1) {
            std::cout << 6 * s * s << '\n';
            continue;
        }
        if (k == 2){
            set<P> st;
            bool ok = false;
            rep(i,0,n){
                if (st.find(ps[i]) == st.end()){
                    st.insert(ps[i]);
                }
                else {
                    ok = true; 
                }
            }
            if (ok){
                cout << 6*s*s << endl;
                continue;
            }
            ll ans = inf;
            rep(i,0,n) {
                rep(j,i+1,n) {
                    if(is_connect(ps[i], ps[j])) {
                        chmin(ans, 6*s*s*2 - cover_sum(ps[i], ps[j]));
                    }
                }
            }
            if(ans == inf) ans = -1;
            std::cout << ans << '\n';
            continue;
        }
        std::vector g(n, std::vector<int>());
        rep(i,0,n) {
            rep(j,i+1,n) {
                if(is_connect(ps[i], ps[j])) {
                    g[i].emplace_back(j);
                    g[j].emplace_back(i);
                }
            }
        }
        std::vector<std::vector<int>> groups;
        {
            std::vector<int> deg1;
            rep(i,0,n) if(g[i].size() == 1) deg1.emplace_back(i);
            std::vector<int> group, seen(n, -1);
            auto dfs = [&](auto &&self, int idx) -> void {
                for(auto v: g[idx]) {
                    if(seen[v] < 0) {
                        seen[v] = 1;
                        group.emplace_back(v);
                        self(self, v);
                    }
                }
            };
            for(auto i: deg1) {
                if(seen[i] > 0) continue;
                group.clear();
                group.emplace_back(i);
                seen[i] = 1;
                dfs(dfs, i);
                groups.emplace_back(group);
            }
            rep(i,0,n) {
                if(seen[i] > 0) continue;
                group.clear();
                seen[i] = 1;
                group.emplace_back(i);
                dfs(dfs, i);
                groups.emplace_back(group);
            }
        }
        ll ans = inf;
        for(auto group: groups) {
            int sz = group.size();
            if(sz < k) continue;
            std::vector<ll> diffs;
            rep(i,0,sz-1) {
                int idx = group[i];
                int jdx = group[i+1];
                diffs.emplace_back(cover_sum(ps[idx], ps[jdx]));
            }
            int w = k-1;
            {
                int idx = group[0];
                int jdx = group.back();
                if(is_connect(ps[idx], ps[jdx])) {
                    if(group.size() == k) w = k;
                    int c = diffs.size();
                    diffs.emplace_back(cover_sum(ps[idx], ps[jdx]));
                    rep(i,0,c) diffs.emplace_back(diffs[i]);
                }
            }
            sz = diffs.size();
            std::vector<ll> cum(sz+1, 0);
            rep(i,0,sz) {
                cum[i+1] = cum[i] + diffs[i];
            }
            rep(i,0,sz) {
                if(i + w > sz) break;
                chmin(ans, 6 * s * s * k - (cum[i+w] - cum[i]));
            }
        }
        if (ans == inf) ans = -1;
        std::cout << ans << '\n';
    }
}
accuracy: 1
time_ms: 110
memory_kb: 3536
final_rank: 18

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n - 1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n - i64(1))); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define Bit(n) (1LL << (n))

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    for (std::size_t i = 0; i < vec.size(); i++)
        os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

using std::size_t;
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;

template <class T, T init>
auto make_vector(int n) {
    return std::vector<T>(n, init);
}

template <class T, T init, typename Head, typename... Tail>
auto make_vector(Head n, Tail... ts) {
    return std::vector(n, make_vector<T, init>(ts...));
}

template <class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T>
T mod_pow(T x, i64 n, i64 mod) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

template <class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T>
struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

}  // namespace ebi

namespace ebi {

void main_() {
    int n, k, s;
    while (std::cin >> n >> k >> s, !(n == 0 && k == 0 && s == 0)) {
        std::vector<std::tuple<i64, i64, i64>> ps(n);
        for (auto &[x, y, z] : ps) {
            std::cin >> x >> y >> z;
        }
        if(k == 1) {
            std::cout << i64(s) * i64(s) * 6 << '\n';
            continue;
        }
        Graph<i64> g(n);
        auto f = [&](int i, int j) -> std::vector<std::tuple<i64, i64, i64>> {
            std::vector<std::tuple<i64, i64, i64>> ret;
            auto [x, y, z] = ps[i];
            auto [nx, ny, nz] = ps[j];
            rep(a, 0, 2) {
                rep(b, 0, 2) {
                    rep(c, 0, 2) {
                        int px = nx + s * a;
                        int py = ny + s * b;
                        int pz = nz + s * c;
                        if (x <= px && px <= x + s && y <= py && py <= y + s &&
                            z <= pz && pz <= z + s) {
                            ret.emplace_back(px, py, pz);
                        }
                    }
                }
            }
            return ret;
        };
        rep(i, 0, n) {
            for (int j = i + 1; j < n; j++) {
                auto ret = f(i, j);
                if (ret.size() == 0) continue;
                auto rhs = f(j, i);
                assert(rhs.size() == ret.size());
                ret.insert(ret.end(), all(rhs));

                i64 res = 0;


                if (ret.size() == 2) {
                    auto [x, y, z] = ret[0];
                    auto [nx, ny, nz] = ret[1];
                    res = 2 * (std::abs(nx - x) * std::abs(ny - y) +
                               std::abs(ny - y) * std::abs(nz - z) +
                               std::abs(nz - z) * std::abs(nx - x));
                } else if (ret.size() == 4 || ret.size() == 8) {
                    auto [x, y, z] = ret[0];
                    int idx = ret.size() / 2;
                    while (idx < (int)ret.size()) {
                        auto [nx, ny, nz] = ret[idx];
                        if (x == nx || y == ny || z == nz) {
                            idx++;
                        }
                        else {
                            break;
                        }
                    }
                    auto [nx, ny, nz] = ret[idx];
                    res = 2 * (std::abs(nx - x) * std::abs(ny - y) +
                               std::abs(ny - y) * std::abs(nz - z) +
                               std::abs(nz - z) * std::abs(nx - x));
                } else {
                    assert(0);
                }
                g.add_edge(i, j, res);
            }
        }
        std::vector<int> seen(n, -1);
        i64 ans = -1;
        std::vector<i64> a;
        int root = -1;
        auto dfs = [&](auto &&self, int v, int par = -1) -> void {
            seen[v] = 1;
            for (auto [nv, cost] : g[v]) {
                if (nv == par) continue;
                if(nv == root) {
                    a.emplace_back(cost);
                    continue;
                }
                if (seen[nv] < 0) {
                    a.emplace_back(cost);
                    self(self, nv, v);
                }
            }
            return;
        };
        rep(i, 0, n) {
            if (g[i].size() == 1 && seen[i] < 0) {
                a.clear();
                dfs(dfs, i);
                if ((int)a.size() < k - 1) continue;
                i64 sum = 0;
                rep(j,0,k-1) {
                    sum += a[j];
                }
                chmax(ans, sum);
                int l = 0, r = k-1;
                while(r < (int)a.size()) {
                    sum -= a[l++];
                    sum += a[r++];
                    chmax(ans, sum);
                }
            }
        }
        rep(i,0,n) {
            if(seen[i] < 0) {
                a.clear();
                root = i;
                dfs(dfs, i);
                if((int)a.size() < k-1) continue;
                if((int)a.size() == k) {
                    chmax(ans, std::accumulate(all(a), i64(0)));
                    continue;
                }
                {
                    auto b = a;
                    a.insert(a.end(), all(b));
                }
                i64 sum = 0;
                rep(j,0,k-1) {
                    sum += a[j];
                }
                int l = 0, r = k-1;
                while(r < (int)a.size()) {
                    sum -= a[l++];
                    sum += a[r++];
                    chmax(ans, sum);
                }
            }
        }
        if(ans > 0) {
            ans = i64(s) * i64(s) * 6 * k - ans;
        }
        std::cout << ans << '\n';
    }
}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3480
final_rank: 6

code_snippet: using namespace std;
#include <bits/stdc++.h>

#define ll long long
#define ul unsigned long
#define dd long double
#define MAX 9223372036854775807
#define REP(i,st,N) for(ll i=st; i<N; i++)

ll sp;

ll solve(vector<ll>& sq1, vector<ll>& sq2, ll s) {
	vector<ll> e(3);
	REP(i, 0, 3) {
		ll mi = min(sq1[i], sq2[i]);
		ll ma = max(sq1[i], sq2[i]);
		e[i] = max(mi + s - ma, 0LL);
		if (e[i] == 0) return 0;
	}
	ll sum = 0;
	REP(i, 0, 3) sum += 2 * e[i] * e[(i + 1) % 3];
	return sum;
}

ll dfs(vector<vector<pair<ll, ll>>>& g, ll st, ll pre, ll k, ll initK, vector<bool>& done) {
	ll ans = -1;
	if (k == 0) {
		for (pair<ll, ll> p : g[st]) if (p.first == sp && initK != 2) return p.second;
		return 0;
	}

	for (pair<ll, ll> p : g[st]) if (p.first != pre && !done[p.first]) {
		done[p.first] = true;
		ll t = dfs(g, p.first, st, k - 1, initK, done);
		if (t >= 0) t += p.second;
		ans = max(ans, t);
		done[p.first] = false;
	}
	return ans;
}

int main() {
	while (1) {
		ll n, k, s; cin >> n >> k >> s;
		if (!(n || k || s)) break;
		vector<vector<ll>> sq;
		ll ma = 6 * s * s * k;
		REP(i, 0, n) {
			vector<ll> c(3);
			cin >> c[0] >> c[1] >> c[2];
			sq.push_back(c);
		}
		if (n == 1 || k == 1) {
			cout << ma << endl;
			continue;
		}
		vector<vector<pair<ll, ll>>> g(n);
		REP(i, 0, n) REP(j, i + 1, n) {
			ll x = solve(sq[i], sq[j], s);
			if (x > 0) {
				g[i].push_back({ j,x });
				g[j].push_back({ i,x });
			}
		}
		ll x = 0;
		vector<bool> done(n, false);
		REP(i, 0, n) {
			sp = i;
			x = max(x, dfs(g, i, -1, k - 1,k, done));
		}
		if (x <= 0) cout << -1 << endl;
		else cout << ma - x << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3456
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using vl = vector<ll>;
template<class T> using vc = vector<T>;
template<class T> using vvc = vector<vector<T>>;

#define eb emplace_back
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define repr(i, n) for (ll i = (n)-1; i >= 0; i--)
#define repe(i, l, r) for (ll i = (l); i < (r); i++)
#define reper(i, l, r) for (ll i = (r)-1; i >= (l); i--)
#define repa(i,n) for (auto& i: n)

template<class T1, class T2> inline bool chmax(T1 &a, const T2 &b) {if (a<b) { a=b; return 1;} return 0;}
template<class T1, class T2> inline bool chmin(T1 &a, const T2 &b) {if (b<a) { a=b; return 1;} return 0;}

struct init{init(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(15);cerr<<fixed<<setprecision(15);}}init_;

template <typename T, typename U> ostream& operator<<(ostream&out,const pair<T, U>&a){return out<<a.first<<' '<<a.second;}
template <typename T> ostream& operator<<(ostream&out, const vector<T>&a){for(auto it=a.begin();it!= a.end();){out<<*it;if(++it!=a.end())out<<' ';}return out;}
template <typename T, size_t N> ostream& operator<<(ostream&out, const array<T, N>&a){for(auto it=a.begin();it!= a.end();){out<<*it;if(++it!=a.end())out<<' ';}return out;}
template <typename T> ostream& operator<<(ostream&out, const set<T>&a){for(auto it=a.begin();it!=a.end();){out<<*it;if(++it!=a.end())out<<' ';}return out;}
template <typename T, typename U> ostream& operator<<(ostream&out, const map<T, U>&a){for(auto it=a.begin();it!=a.end();){out<<*it;if(++it!=a.end())out<<'\n';}return out;}

#ifdef DEBUG
template <class T, class N> void verr(const vector<T>& a, const N& n) { rep(i, n) cerr << a[i] << " "; cerr << endl; }
template <class T, class N, size_t AN> void verr(const array<T, AN>& a, const N& n) { rep(i, n) cerr << a[i] << " "; cerr << endl; }
ll dbgt = 1; void err() { cerr << "passed " << dbgt++ << endl; }
template<class H, class... T> void err(H&& h,T&&... t){ cerr<< h << (sizeof...(t)?" ":"\n") << flush; if(sizeof...(t)>0) err(forward<T>(t)...); }
#else
void err(){}
template <class H, class... T>
void err(H &&h, T &&...t) {}
template <class H, class... T>
void verr(H &&h, T &&...t) {}
#endif

const ll INF = 4e18;
const ld EPS = 1e-11;
const ld PI = acos(-1.0L);
// const ll MOD = 1e9 + 7;
const ll MOD = 998244353;
//--------------------------------------------------------------------------------//
struct point {
    int x, y, z;
    point(){}
    point(int x, int y, int z): x(x), y(y), z(z){}
};

struct UnionFind {
private:
    vector<int> par;
    vector<int> count;
    vector<int> rank;
public:
    UnionFind(int N) {
        count.assign(N, 1);
        rank.assign(N, 0);
        par.assign(N, 0);
        rep(i, N) par[i] = i;
    }

    int root(int x) {
        if (par[x] == x)
            return x;
        else {
            par[x] = root(par[x]);
            return par[x];
        }
    }

    void unite(int x, int y) {
        x = root(x), y = root(y);
        if (x == y) return;
        if (rank[x] < rank[y])
            swap(x, y);
        else if (rank[x] == rank[y])
            rank[y]++;
        par[y] = x;
        count[x] += count[y];
        return;
    }

    int size(int x) {
        return count[root(x)];
    }

    bool issame(int x, int y) {
        return root(x) == root(y);
    }
};
using UF = struct UnionFind;


void solve(int N, int K, int S){
    // err(N, K, S);
    vc<point> ps(N);
    rep(i, N) cin >> ps[i].x >> ps[i].y >> ps[i].z;
    if(K == 1) {
        cout << 6 * S * S << endl;
        return;
    }

    auto dup = [&](point p1, point p2) -> int {
        ll s = 1, ssum = 0;
        if (p1.x >= p2.x + S or p2.x >= p1.x + S) return 0;
        int dx = min(p1.x + S - p2.x, p2.x + S - p1.x);
        if(p1.y >= p2.y + S or p2.y >= p1.y + S) return 0;
        int dy = min(p1.y + S - p2.y, p2.y + S - p1.y);
        if (p1.z >= p2.z + S or p2.z >= p1.z + S) return 0;
        int dz = min(p1.z + S - p2.z, p2.z + S - p1.z);
        ssum = 2 * (dx * dy + dy * dz + dz * dx);
        return ssum;
    };

    UF ufall(N);
    vvc<pair<int, int>> G(N);
    rep(i, N) repe(j, i + 1, N) {
        auto s = dup(ps[i], ps[j]);
        if(s > 0) {
            G[i].eb(j, s);
            G[j].eb(i, s);
            ufall.unite(i, j);
        }
    }

    ll ans = INF;
    rep(rt, N) {
        if (ufall.size(rt) < K) continue;

        bool iscycle = true;
        int v1;
        rep(i, N) {
            if (!ufall.issame(i, rt)) continue;
            if (G[i].size() < 2) {
                iscycle = false;
                v1 = i;
            }
        }

        if (iscycle) {
            vl es;
            int cur = rt, par = G[cur][0].first;
            int ncur, npar;
            do {
                for(auto[to, ts]: G[cur]) {
                    if (to == par) continue;
                    es.eb(ts);
                    tie(ncur, npar) = {to, cur};
                }
                // err("cp", cur, par);
                tie(cur, par) = {ncur, npar};
            } while (cur != rt);
            int en = es.size();
            if(ufall.size(rt) == K) {
                chmin(ans, K * 6 * S * S - accumulate(all(es), 0ll));
                // err("pass", K * 6 * S * S - accumulate(all(es), 0ll), en);
                continue;
            }
            vl acc(en * 2 + 1);
            rep(i, 2 * en) acc[i + 1] = acc[i] + es[i % en];
            repe(i, K - 1, en * 2) chmin(ans, K * 6 * S * S - (acc[i] - acc[i - K + 1]));
        } else {
            vl es;
            int cur = v1, par = -1;
            int ncur, npar;
            while (true) {
                bool update = false;
                for(auto[to, ts]: G[cur]) {
                    if (to == par) continue;
                    es.eb(ts);
                    update = true;
                    tie(ncur, npar) = {to, cur};
                }
                if (!update) break;
                tie(cur, par) = {ncur, npar};
            }
            int en = es.size();
            vl acc(en + 1);
            rep(i, en) acc[i + 1] = acc[i] + es[i];
            repe(i, K - 1, en + 1) chmin(ans, K * 6 * S * S - (acc[i] - acc[i - K + 1]));
        }
    }
    cout << (ans == INF ? -1 : ans) << endl;
}

int main() {
    int counter = 0;
    while (true) {
        int N, K, S;
        cin >> N >> K >> S;
        counter++;
        if (N == 0) break;
        solve(N, K, S);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3440
final_rank: 4

code_snippet: //Let's join Kaede Takagaki Fan Club !!
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cassert>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <iostream>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cassert>
#include <iomanip>
#include <chrono>
#include <random>
#include <bitset>
#include <complex>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
#define int long long
//#define L __int128
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define a first
#define b second
#define fi first
#define sc second
#define rng(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
#define all(x) x.begin(),x.end()
#define si(x) int(x.size())
 
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif
 
template<class t,class u> bool chmax(t&a,u b){if(a<b){a=b;return true;}else return false;}
template<class t,class u> bool chmin(t&a,u b){if(b<a){a=b;return true;}else return false;}
 
template<class t> using vc=vector<t>;
 
template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.fi<<","<<p.sc<<"}";
}
 
template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}
 

template<class T>
void o(const T &a,bool space=false){
	cout << a << (space?' ':'\n');
}
//ios::sync_with_stdio(false);
//const ll mod = 998244353;
const ll mod = 1000000007;
mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());
template<class T>
void add(T&a,T b){
	a+=b;
	if(a >= mod) a-=mod;
}
ll modpow(ll x,ll n){
	ll res=1;
	while(n>0){
		if(n&1) res=res*x%mod;
		x=x*x%mod;
		n>>=1;
	}
	return res;
}
#define _sz 1
ll F[_sz],R[_sz];
void make(){
	F[0] = 1;
	for(int i=1;i<_sz;i++) F[i] = F[i-1]*i%mod;
	R[_sz-1] = modpow(F[_sz-1], mod-2);
	for(int i=_sz-2;i>=0;i--) R[i] = R[i+1] * (i+1) % mod;
}
ll C(int a,int b){
	if(b < 0 || a < b) return 0;
	return F[a]*R[b]%mod*R[a-b]%mod;
}
//複数テストケースなので積み上げる変数はローカルに！
//置けないなら必ず初期化！
int n, k, s, x[2005], y[2005], z[2005];
void solve(){
	//最初の入力は済んでいる
	rep(i, n) cin >> x[i] >> y[i] >> z[i];
	auto area = [&](P p, P q){
		int x = min(p.a + s, q.a + s) - max(p.a, q.a);
		int y = min(p.b + s, q.b + s) - max(p.b, q.b);
		chmax(x, 0LL);
		chmax(y, 0LL);
		return x*y;
	};
	vc<vc<P>>edge(n);
	rep(i, n){
		rep(j, i){
			int f = area(mp(x[j], y[j]), mp(x[i], y[i]));
			int g = area(mp(x[j], z[j]), mp(x[i], z[i]));
			int h = area(mp(z[j], y[j]), mp(z[i], y[i]));
			if(!f or !g or !h) continue;
			
			edge[i].eb(j, f + g + h);
			edge[j].eb(i, f + g + h);
		}
	}
	int ans = -1e18;
	rep(i, n){
		if(k == 1){
			chmax(ans, 0LL);
			continue;
		}
		for(auto a:edge[i]){
			vc<int>vis(n, 0);
			vis[i] = 1;
			
			int cur = a.a;
			int tmp = a.b;
			int zan = k-1;
			while(1){
				if(vis[cur]) break;
				vis[cur] = 1;
				zan --;
				if(zan == 0) {
					if(k > 2){
						for(auto a:edge[cur]){
							if(a.a == i){
								tmp += a.b;
							}
						}
					}
					break;
				}
				for(auto a:edge[cur]){
					if(!vis[a.a]) {
						cur = a.a;
						tmp += a.b;
						break;
					}
				}
			}
			if(!zan) chmax(ans, tmp);
		}
	}
	if(ans < 0) o(-1);
	else o(2LL * (3LL*s*s*k - ans));
}
signed main(){
	//cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);
	while(true){
		cin>>n>>k>>s;
		//終了条件
		if(!n) return 0;
		solve();
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3244
final_rank: 1

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <climits>
#include <string>
#include <cmath>
#include <bitset>
#include <complex>
#include <functional>
#include <ctime>
#include <cassert>
#include <fstream>
#include <stack>
#include <random>
#include <iomanip>
#include <time.h>
#include <list>
#include <unordered_map>

#include <algorithm>
#include <array>

using namespace std;
typedef long long ll;
typedef long double dd;
typedef vector<ll> vl;
typedef vector<dd> vd;
typedef vector<vector<ll>> vvl;
typedef vector<vector<dd>> vvd;
//#define i_7 (ll)(1E9+7)
#define i_7 998244353
#define i_5 i_7-2
ll mod(ll a){
    ll c=a%i_7;
    if(c>=0)return c;
    return c+i_7;
}
typedef pair<ll,ll> l_l;
typedef pair<dd,dd> d_d;
ll inf=(ll)1E18;
#define rep(i,l,r) for(ll i=l;i<=r;i++)
#define pb push_back
ll max(ll a,ll b){if(a<b)return b;else return a;}
ll min(ll a,ll b){if(a>b)return b;else return a;}
dd EPS=1E-6;
dd PI=acos(-1);
#define endl "\n"
#define fastio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);



struct Edge{
    ll to,cost;
    Edge(ll to, ll cost){
        this->to = to;
        this->cost = cost;
    }
};

ll hoge;

void dfs(ll idx, vector<bool> &seen, const vector<vector<Edge>> &v, vector<ll> &tmp){
    seen[idx] = true;
    hoge=idx;
    for(Edge e : v[idx]){
        if(seen[e.to])continue;
        tmp.pb(e.cost);
        dfs(e.to, seen, v, tmp);
    }
}


signed main(){fastio
    while(true){
        ll n,K,s;cin>>n>>K>>s;
        if(n==0)break;
        vvl x(n);
        rep(i,0,n-1){
            x[i].resize(3);
            cin>>x[i][0]>>x[i][1]>>x[i][2];
        }
        vector<vector<Edge>> v(n);
        rep(i,0,n-1){
            rep(j,0,n-1){
                if(i>=j)continue;
                bool ok = true;
                vl u;
                rep(k,0,2){
                    if(x[j][k]<=x[i][k] && x[i][k]<=x[j][k]+s){
                        u.pb(x[j][k]+s-x[i][k]);
                    }else if(x[i][k]<=x[j][k] && x[j][k]<=x[i][k]+s){
                        u.pb(x[i][k]+s-x[j][k]);
                    }else{
                        ok = false;
                    }
                }
                if(ok){
                    ll pro=0;
                    rep(k,0,2){
                        rep(l,0,2){
                            if(k<l){
                                pro += 2*u[k]*u[l];
                            }
                        }
                    }
                    ll cost = pro;
                    v[i].pb(Edge(j,cost));
                    v[j].pb(Edge(i,cost));
                }
            }
        }
        vector<bool> seen(n, false);
        ll ans=inf;
        rep(i,0,n-1){
            if(seen[i])continue;
            if(v[i].size() == 0){
                if(K==1){
                    ans = min(ans, 6*s*s);
                }
                continue;
            }
            vector<ll> tm;
            bool loop = false;
            if(v[i].size() == 1){
                dfs(i, seen, v, tm);
            }else{
                seen[i] = true;
                vector<ll> tmp;
                tmp.pb(v[i][0].cost);
                dfs(v[i][0].to, seen, v, tmp);
                if(hoge == v[i][1].to)loop = true;
                vector<ll> tmp2;
                tmp2.pb(v[i][1].cost);
                if(!seen[v[i][1].to]){
                    dfs(v[i][1].to, seen, v, tmp2);
                }
                reverse(tmp2.begin(), tmp2.end());
                for(ll co : tmp2){
                    tm.pb(co);
                }
                for(ll co : tmp){
                    tm.pb(co);
                }
            }
            ll num;
            if(loop){
                num = tm.size();
            }else{
                num = tm.size() + 1;
            }
            if(num < K){
                continue;
            }
            ll m = tm.size();
            vl sum(m+1,0);
            rep(i,1,m){
                sum[i] = sum[i-1] + tm[i-1];
            }
            ll maxi = 0;
            if(loop){
                if(K==num){
                    maxi = sum[m];
                }else{
                    rep(j,K-1,m+(K-1)-1){
                        if(j<=m){
                            maxi = max(maxi, sum[j]-sum[j-(K-1)]);
                        }else{
                            maxi = max(maxi, sum[m]-sum[j-(K-1)]+sum[j-m]);
                        }
                    }
                }
            }else{
                rep(j,K-1,m){
                    maxi = max(maxi, sum[j]-sum[j-(K-1)]);
                }
            }
            ans = min(ans, 6*s*s*K - maxi);
        }
        if(ans == inf){
            cout<<-1<<endl;
        }else{
            cout<<ans<<endl;
        }
    }
    
    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3508
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using ll = long long;
#define var auto
const char newl = '\n';

using namespace std;

template<typename T1, typename T2> inline void chmin(T1& a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> inline void chmax(T1& a, T2 b) { if (a < b) a = b; }

const ll inf = INT32_MAX;

struct Box;
bool ow(Box a, Box b);

ll w;

struct Box {
  ll x, y, z;
  ll s() {
    return w * w * 6;
  }
  ll eats(Box& a) {
    if (not ow(*this, a)) return 0;
    var dx = w - abs(x - a.x);
    var dy = w - abs(y - a.y);
    var dz = w - abs(z - a.z);
    assert(dx <= w && dy <= w && dz <= w);
    ll res = 0;
    return (dx * dy + dy * dz + dz * dx) * 2;
  }
};

bool ow(Box a, Box b) {
  ll maxdist = 0;
  chmax(maxdist, abs(a.x - b.x));
  chmax(maxdist, abs(a.y - b.y));
  chmax(maxdist, abs(a.z - b.z));
  assert(maxdist != w);
  return maxdist < w;
}

struct Boxes {
  ll s = 0;
  deque<Box> q;
  Box prev2;
  Box prev1;

  void check() {
    ll res = 0;
    for (int i = 0; i < q.size(); i++) {
       res += q[i].s();
       if (i == 0) continue;
       res -= q[i].eats(q[i - 1]);
    }
    if (res != s) {
      cout << "";
    }
    assert(res == s);
  }

  void push(Box cur) {
    check();
    if (q.size() != 0) {
      s -= cur.eats(q.back());
    }
    s += cur.s();
    q.emplace_back(cur);
  }
  void pop() {
    check();
    assert(!q.empty());
    var popped = q.front(); q.pop_front();
    s -= popped.s();
    if (q.size() == 0) return;
    s += popped.eats(q.front());
  }
};

struct UnionFind {
  int num;
  vector<int> rs, ps;
  UnionFind(int n) :num(n), rs(n, 1), ps(n, 0) {
    iota(ps.begin(), ps.end(), 0);
  }
  int find(int x) {
    return (x == ps[x] ? x : ps[x] = find(ps[x]));
  }
  bool same(int x, int y) {
    return find(x) == find(y);
  }
  void unite(int x, int y) {
    x = find(x); y = find(y);
    if (x == y) return;
    if (rs[x] < rs[y]) swap(x, y);
    rs[x] += rs[y];
    ps[y] = x;
    num--;
  }
  int size(int x) {
    return rs[find(x)];
  }
  int count() const {
    return num;
  }
};

bool solve() {
  int n, k;
  cin >> n >> k >> w;
  if (n == 0) return false;
  vector<Box> v(n);
  for (var&& item : v) cin >> item.x >> item.y >> item.z;

  vector<vector<int>> graph(n);
  UnionFind uf(n);
  for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
      if (ow(v[i], v[j])) {
        uf.unite(i, j);
        graph[i].emplace_back(j);
        graph[j].emplace_back(i);
      }
    }
  }


  const ll inf = LLONG_MAX;
  ll res = inf;

  for (int id = 0; id < n; id++) {
    bool has_point = false;
    int first = -1;
    for (int i = 0; i < n; i++) {
      if (uf.find(i) != id) continue;
      if (graph[i].size() == 1) {
        if (not has_point) {
          first = i;
        }
        has_point = true;
        continue;
      }
      if (not has_point) {
        first = i;
      }
    }

    if (first == -1) continue;
    if (uf.size(first) < k) continue;

    int last = -1;
    int cur = first;
    Boxes b; b.push(v[cur]);

    while (b.q.size() < k) {
      for (var&& adj : graph[cur]) {
        if (adj == last) continue;
        b.push(v[adj]);
        last = cur;
        cur = adj;
        break;
      }
    }

    assert(b.q.size() == k);

    if (k != 1 && uf.size(first) == k && not has_point) {
      b.s -= b.q.front().eats(b.q.back());
      chmin(res, b.s);
      continue;
    }

    ll curres = b.s;

    int cnt = has_point ? (uf.size(first) - k) : (uf.size(first) - 1);
    for (int _ = 0; _ < cnt; _++) {
      b.pop();
      for (var&& adj : graph[cur]) {
        if (adj == last) continue;
        b.push(v[adj]);
        last = cur;
        cur = adj;
        break;
      }
      assert(b.q.size() == k);
      chmin(curres, b.s);
    }

    chmin(res, curres);
  }
  if (res == inf) res = -1;
  cout << res << endl;
  return true;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  while (solve());
}
accuracy: 1
time_ms: 10
memory_kb: 3432
final_rank: 2

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
using namespace std;
 
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;
 
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
 
 
#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()
 
#define MOD 1000000007
 
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
const double EPS = 1e-8, PI = acos(-1);
const double pi = 3.141592653589793238462643383279;
//ここから編集    
typedef string::const_iterator State;
ll GCD(ll a, ll b){
  return (b==0)?a:GCD(b, a%b);
}
ll LCM(ll a, ll b){
  return a/GCD(a, b) * b;
}
template< int mod >
struct ModInt {
  int x;
 
  ModInt() : x(0) {}
 
  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
 
  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }
 
  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }
 
  ModInt operator-() const { return ModInt(-x); }
 
  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
 
  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
 
  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
 
  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
 
  bool operator==(const ModInt &p) const { return x == p.x; }
 
  bool operator!=(const ModInt &p) const { return x != p.x; }
 
  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
 
  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
 
  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }
 
  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }
 
  static int get_mod() { return mod; }
};
 
using modint = ModInt< 998244353 >;
template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;
 
  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(int i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(int i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(int i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }
 
  inline T fact(int k) const { return _fact[k]; }
 
  inline T rfact(int k) const { return _rfact[k]; }
 
  inline T inv(int k) const { return _inv[k]; }
 
  T P(int n, int r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }
 
  T C(int p, int q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }
 
  T H(int n, int r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};
 
ll modpow(ll x, ll n, ll mod) {
  ll res = 1;
  x %= mod;
  if(x == 0) return 0;
  while(n) {
    if(n&1) res = (res * x) % mod;
    x = (x * x) % mod;
    n >>= 1;
  }
  return res;
} 
inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}
template<typename T> 
struct BIT{
  int N;
  std::vector<T> node;
  BIT(){}
  BIT(int n){
    N = n;
    node.resize(N+10);
  }
  void build(int n) {
    N = n;
    node.resize(N+10);
  }
  /* a: 1-indexed */
  void add(int a, T x){
    for(int i=a; i<(int)node.size(); i += i & -i) node[i] += x;
  }

  /* [1, a] */
  T sum(int a){
    T res = 0;
    for(int x=a; x>0; x -= x & -x) res += node[x];
    return res;
  }

  /* [l, r] */
  T rangesum(int l, int r){
    return sum(r) - sum(l-1);
  }

  /* 
    a1+a2+...+aw >= valとなるような最小のwを返す
    @verify https://codeforces.com/contest/992/problem/E
  */
  int lower_bound(T val) {
    if(val < 0) return 0;

    int res = 0;
    int n = 1; 
    while (n < N) n *= 2;

    T tv=0;
    for (int k = n; k > 0; k /= 2) {
      if(res + k < N && node[res + k] < val){
        val -= node[res+k];
        res += k;
      }
    }
    return res+1; 
  }
};
struct UnionFind{
  std::vector<int> par;
  std::vector<int> siz;

  UnionFind(int sz_): par(sz_), siz(sz_) {
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  void init(int sz_){
    par.resize(sz_);
    siz.resize(sz_);
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  int root(int x){
    if(x == par[x]) return x;
    return par[x] = root(par[x]);
  }

  bool merge(int x, int y){
    x = root(x), y = root(y);
    if(x == y) return false;
    if(siz[x] < siz[y]) std::swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    return true;
  }

  bool issame(int x, int y){
    return root(x) == root(y);
  }

  int size(int x){
    return siz[root(x)];
  }
};
struct RollingHash{

    using ull = unsigned long long;
    const ull mod = (1ULL << 61) - 1;
    const ull MASK30 = (1ULL << 30) - 1;
    const ull MASK31 = (1ULL << 31) - 1;

    const ull MASK61 = mod;

    ull base;
    int n;
    vector<ull> hash, pow;

    RollingHash(const string &s)
    {
        random_device rnd;
        mt19937_64 mt(rnd());
        base = 1001;
        
        n = (int)s.size();
        hash.assign(n+1, 0);
        pow.assign(n+1, 1);
        
        for(int i=0; i<n; i++){
            hash[i+1] = calc_mod(mul(hash[i], base) + s[i]);
            pow[i+1] = calc_mod(mul(pow[i], base));
        }
    }

    ull calc_mod(ull x){
        ull xu = x >> 61;
        ull xd = x & MASK61;
        ull res = xu + xd;
        if(res >= mod) res -= mod;
        return res;
    }

    ull mul(ull a, ull b){
        ull au = a >> 31;
        ull ad = a & MASK31;
        ull bu = b >> 31;
        ull bd = b & MASK31;
        ull mid = ad * bu + au * bd;
        ull midu = mid >> 30;
        ull midd = mid & MASK30;
        return calc_mod(au * bu * 2 + midu + (midd << 31) + ad * bd);
    }

    //[l,r)のハッシュ値
    inline ull get(int l, int r){
        ull res = calc_mod(hash[r] + mod*3-mul(hash[l], pow[r-l]));
        return res;
    }
    //string tのハッシュ値
    inline ull get(string t){
        ull res = 0;
        for(int i=0; i<t.size(); i++){
            res = calc_mod(mul(res, base)+t[i]);
        }
        return res;
    }
    //string s中のtの数をカウント
    inline int count(string t) {
        if(t.size() > n) return 0;
        auto hs = get(t);
        int res = 0;
        for(int i=0; i<n-t.size()+1; i++){
            if(get(i, i+t.size()) == hs) res++; 
        }
        return res;
    }

    /* 
        concat 
        @verify https://codeforces.com/problemset/problem/514/C
    */
    inline ull concat(ull h1, ull h2, int h2len){
      return calc_mod(h2 + mul(h1, pow[h2len]));
    }

    // LCPを求める S[a:] T[b:]
    inline int LCP(int a, int b){
        int len = min((int)hash.size()-a, (int)hash.size()-b);
        
        int lb = -1, ub = len;
        while(ub-lb>1){
            int mid = (lb+ub)/2;

            if(get(a, a+mid) == get(b, b+mid)) lb = mid;
            else ub = mid;
        }
        return lb;
    }
};
int h;
ll ans = (1LL<<60);
ll x[2010], y[2010], z[2010];
int n, k, s;
set<int> st;
void dfs(int v, int p, int nokori, vector<vector<pair<ll,ll>>> &g, ll sum) {
  ll t = sum;
  for(auto[u, cost]: g[v]) {
    if(u != p && st.find(u) != st.end()) t -= cost;
  }

  if(nokori == 0) {
    ans = min(ans, t);
    return ;
  }
  
  for(auto[u, cost]: g[v]) {
    if(p == u) continue;
    if(st.find(u) != st.end()) continue;
    st.insert(u);
    dfs(u, v, nokori-1, g, t + 6 * s * s - cost);
    st.erase(u);
  }

}
int main() {  
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(12);

    while(cin >> n >> k >> s) {
      if(n == 0 && k == 0 && s == 0) break;
      REP(i,n) cin >> x[i] >> y[i] >> z[i];
      vector<vector<pair<ll,ll>>> g(n);
      st.clear();
      ans = (1LL<<60);
      for(int i=0; i<n; i++) {
        for(int j=i+1; j<n; j++) {

          int ax = x[i], bx = x[i] + s, cx = x[j], dx = x[j] + s;
          if(bx < cx) continue;
          if(dx < ax) continue;
          int ay = y[i], by = y[i] + s, cy = y[j], dy = y[j] + s;
          if(by < cy) continue;
          if(dy < ay) continue;
          int az = z[i], bz = z[i] + s, cz = z[j], dz = z[j] + s;
          if(bz < cz) continue;
          if(dz < az) continue;

          
          vector<ll> a;
          if(ax <= cx && cx <= bx) a.push_back(bx-cx);
          else a.push_back(dx-ax);
          if(ay <= cy && cy <= by) a.push_back(by-cy);
          else a.push_back(dy-ay);
          if(az <= cz && cz <= bz) a.push_back(bz-cz);
          else a.push_back(dz-az);
          ll t = 2*a[0]*a[1]+2*a[0]*a[2]+2*a[1]*a[2];
          g[i].push_back({j,t});
          g[j].push_back({i,t});
        }
      }
      for(int i=0; i<n; i++) {
        st.insert(i);
        dfs(i, -1, k-1, g, 6 * s * s);
        st.erase(i);
      }
      if(ans == (1LL<<60)) ans = -1;
      cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3480
final_rank: 16

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i = 0; i < (n); i++)
using namespace std;
typedef long long ll;

int main(){
    cin.tie(0);
    ios::sync_with_stdio(0);
    
    while(true) {
        int n,k,s; cin >> n >> k >> s; if(n == 0) break;
        vector<vector<pair<int,int>>> G(n);
        vector<int> x(n), y(n), z(n);
        rep(i,n) cin >> x[i] >> y[i] >> z[i];

        if(k == 1) { cout << 6 * s * s << endl; continue; }

        auto calc = [&](int i, int j) {
            int dx = s - abs(x[i] - x[j]);
            int dy = s - abs(y[i] - y[j]);
            int dz = s - abs(z[i] - z[j]);
            if(dx <= 0 || dy <= 0 || dz <= 0) return 0;
            return 2 * (dx * dy + dy * dz + dz * dx);
        };

        rep(i,n)rep(j,n)if(i < j) {
            int cost = calc(i, j);
            if(cost != 0) {
                G[i].push_back({j, cost});
                G[j].push_back({i, cost});
            }
        }

        int ans = 0;
        rep(S,n) {
            for(auto to : G[S]) {
                int T = to.first;
                vector<int> can;
                vector<bool> used(n, false);
                can.push_back(T); used[T] = true;
                can.push_back(S); used[S] = true;

                bool f = (k == 2);
                rep(_,k-2) {
                    f = false;
                    for(auto nt : G[T]) {
                        if(!used[nt.first]) {
                            f = true;
                            used[nt.first] = true;
                            T = nt.first;
                            can.push_back(T);
                            break;
                        }
                    }
                }

                if(!f) continue;
                int sum = 0;
                for(int i : can) for(int j : can) 
                    if(i < j) sum += calc(i, j);
                ans = max(ans, sum);
            }
        }
        
        cout << (ans == 0 ? -1 : 6 * s * s * k - ans) << endl;
    }
}
accuracy: 1
time_ms: 120
memory_kb: 3520
final_rank: 20

code_snippet: //#include<atcoder/all>

#ifndef ATCODER_MODINT_HPP
#define ATCODER_MODINT_HPP 1

//#include <atcoder/internal_math>
#ifndef ATCODER_INTERNAL_MATH_HPP
#define ATCODER_INTERNAL_MATH_HPP 1

#include <utility>

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast moduler by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    for (long long a : {2, 7, 61}) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_MATH_HPP

//#include <atcoder/internal_type_traits>
#ifndef ATCODER_INTERNAL_TYPE_TRAITS_HPP
#define ATCODER_INTERNAL_TYPE_TRAITS_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_TYPE_TRAITS_HPP

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_MODINT_HPP


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef ATCODER_DSU_HPP
#define ATCODER_DSU_HPP 1

#include <algorithm>
#include <cassert>
#include <vector>

namespace atcoder {

// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
  public:
    dsu() : _n(0) {}
    dsu(int n) : _n(n), parent_or_size(n, -1) {}

    int merge(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
        parent_or_size[x] += parent_or_size[y];
        parent_or_size[y] = x;
        return x;
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return leader(a) == leader(b);
    }

    int leader(int a) {
        assert(0 <= a && a < _n);
        if (parent_or_size[a] < 0) return a;
        return parent_or_size[a] = leader(parent_or_size[a]);
    }

    int size(int a) {
        assert(0 <= a && a < _n);
        return -parent_or_size[leader(a)];
    }

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = leader(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                           [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }

  private:
    int _n;
    // root node: -1 * component size
    // otherwise: parent
    std::vector<int> parent_or_size;
};

}  // namespace atcoder

#endif  // ATCODER_DSU_HPP









using namespace atcoder;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//typedef int ll;

void mod_print(ll k){
   // const ll i_7=998244353;
    const ll i_7 =(ll)(1E9+7);
    auto mod=[&](ll a){
        ll c=a%i_7;
        if(c>=0)return c;
        return c+i_7;
    };
    ll P=50000;
    for(ll y=1;y<=P;y++){
        ll x=mod(y*k);
        if(abs(x)<=P||x+P>=i_7){
            if(x+P>=i_7){
                x-=i_7;
            }
            cerr<<x<<"/"<<y<<" ";
            //cerr<<setprecision(5)<<(dd)x/(dd)y<<" ";
            return;
        }
    }
    cerr<<"nun"<<endl;
}
/*
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
namespace multi = boost::multiprecision;
typedef multi::cpp_int LL;
typedef multi::number<multi::cpp_dec_float<1024>> DD;// 仮数部が1024ビットの浮動小数点数型(TLEしたら小さくする)
//*/
typedef long double dd;
typedef pair<ll,ll> l_l;
typedef pair<dd,dd> d_d;
ll inf=(ll)1E18;
#define rep(i,l,r) for(ll i=l;i<=r;i++)
#define rrep(i,r,l) for(ll i=r;i>=l;i--)
#define pb push_back
ll max(ll a,ll b){if(a<b)return b;else return a;}
ll min(ll a,ll b){if(a>b)return b;else return a;}
dd EPS=1E-12;
#define fi first
#define se second

#define SORT(v) sort(v.begin(),v.end())
#define ERASE(v) sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end())
#define POSL(v,x) (lower_bound(v.begin(),v.end(),x)-v.begin())
#define POSU(v,x) (upper_bound(v.begin(),v.end(),x)-v.begin())
template<class T,class S>
inline bool chmax(T &a, S b) {
    if(a < b) {
        a = (T)b;
        return true;
    }
    return false;
}
template<class T,class S>
inline bool chmin(T &a, S b) {
    if(a > b) {
        a = (T)b;
        return true;
    }
    return false;
}
#define all(c) c.begin(),c.end()

//using mint = modint998244353;
using mint = modint1000000007;
//using mint=modint;
//using mint=static_modint<100>;
//using mint=dd;
//using mint=ll;

typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<vvl>vvvl;
typedef vector<mint>vi;
typedef vector<vi>vvi;
typedef vector<vvi>vvvi;
typedef vector<vvvi>vvvvi;
typedef vector<l_l>vl_l;
typedef vector<vl_l>vvl_l;
typedef vector<string>vs;
typedef vector<vs>vvs;
typedef vector<dd> vd;
typedef vector<vd> vvd;
typedef vector<vvd> vvvd;
typedef vector<d_d>vd_d;
dd PI=acos((dd)-1);

#define fastio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cout<<setprecision(20);
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;

// g++ -std=gnu++17 -Wall -Wextra -O2 -DONLINE_JUDGE main.cpp && ./a.out
#define endl "\n"  //インタラクティブで消す！！！！！！！！！！！！！！！！！！！！！
#define popcount __builtin_popcountll
#define SHUFFLE(v) shuffle(all(v),default_random_engine(chrono::system_clock::now().time_since_epoch().count()))
//////////////////////////////////////////////////////////////////////////////
template<class S>
void DEBUG_PRINT(S x){
    cerr<<x<<endl;
}
template<class S,class T>
void DEBUG_PRINT(pair<S,T>x){
    cerr<<"("<<x.fi<<","<<x.se<<")"<<endl;
}
template<class S>
void DEBUG_PRINT(vector<S> x){
    for(auto y:x)cerr<<setw(2)<<y<<" ";
    cerr<<endl;
}
template<class S,class T>
void DEBUG_PRINT(vector<pair<S,T>>x){
    for(auto y:x)cerr<<"("<<y.fi<<","<<y.se<<") ";
    cerr<<endl;
}
template<class S>
void DEBUG_PRINT(vector<vector<S>> x){
    cerr<<endl;
    for(auto y:x){
        for(auto z:y){
            cerr<<setw(2)<<z<<" ";
        }cerr<<endl;
    }cerr<<endl;
}

#define TO_STRING_FOR_DEBUG(VariableName) # VariableName
#ifdef LOCAL
#define DEB(V) cerr<< TO_STRING_FOR_DEBUG(V) << ": "; DEBUG_PRINT(V);
#else
#define DEB(V) void(0)
#endif
/////////////////////////////////////////////////////////////////////////////////////////

void solve(){
    ll n,k,s;cin>>n>>k>>s;
    if(n==0)exit(0);
    vvl a(n,vl(3));
    rep(i,0,n-1)rep(j,0,2)cin>>a[i][j];
    
    if(k==1){
        cout<<6*s*s<<endl;return ;
    }
    
    vvl_l v(n);
    rep(i,0,n-1){
        rep(j,i+1,n-1){
            auto calc=[](vl a,vl b,ll s){
                vl v;
                rep(i,0,2){
                    ll dis=abs(a[i]-b[i]);
                    if(dis>=s){
                        return 0ll;
                    }else{
                        v.pb(s-dis);
                    }
                }
                ll ans=0;
                rep(i,0,2){
                    rep(j,i+1,2){
                        ans += v[i]*v[j];
                    }
                }
                return ans*2;
            };
            ll E=calc(a[i],a[j],s);
            if(E==0)continue;
            v[i].pb({j,E});
            v[j].pb({i,E});
        }
    }
    rep(i,0,n-1){
        cerr<<i<<":";
        DEB(v[i]);
    }
    dsu d(n);
    rep(i,0,n-1){
        for(auto x:v[i]){
            d.merge(i,x.fi);
        }
    }
    map<l_l,ll>mp;
    rep(i,0,n-1){
        for(auto x:v[i]){
            mp[{i,x.fi}] = x.se;
        }
    }
    auto G=d.groups();
    vl used(n);
    ll MAX =0;
    for(auto g:G){
        ll sz=g.size();
        ll edge_cnt=0;
        for(auto x:g){
            for(auto y:v[x]){
                if(x>y.fi)continue;
                edge_cnt ++;
            }
        }
        assert(edge_cnt == sz || edge_cnt == sz-1);
        
        if(sz<k)continue;
        
        ll pos=g[0];
        if(edge_cnt == sz-1){
            for(auto x:g){
                if((int)v[x].size()==1){
                    pos=x;
                    break;
                }
            }
            assert((int)v[pos].size()==1);
        }
        
        vl vec={pos};
        used[pos]=true;
        while(1){
            bool bre=true;
            for(auto x:v[pos]){
                if(used[x.fi])continue;
                used[x.fi]=true;
                pos=x.fi;
                vec.pb(x.fi);
                bre=false;
                break;
            }
            if(bre)break;
        }
        assert((int)vec.size() == sz);
        
        auto callast=[&](vl v){
            rep(i,0,(int)v.size()-1){
                ll sum=0;
                rep(j,i,i+k-2){//k-1個
                    if(j>=(int)v.size()){
                        return;
                    }
                    sum += v[j];
                }
                chmax(MAX,sum);
            }
        };
        if(edge_cnt == sz-1){
            vl v;
            rep(i,0,sz-2){
                v.pb(mp[{vec[i],vec[i+1]}]);
            }
            callast(v);
        }else{
            if(sz==k){
                ll sum=0;
                rep(i,0,sz-1){//k個
                    sum += mp[{vec[i%sz],vec[(i+1)%sz]}];
                }
                chmax(MAX,sum);
            }else{
                vl v;
                rep(i,0,2*sz){
                    v.pb(mp[{vec[i%sz],vec[(i+1)%sz]}]);
                }
                callast(v);
            }
        }
    }
    if(MAX==0){
        cout<<-1<<endl;
    }else{
        cout<<k*6*s*s - MAX<<endl;
    }
}

signed main(){fastio
    
    while(1){
        solve();
    }
    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3564
final_rank: 8