#include <iostream>
#include <vector>
#include <array>
#include <list>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
#include <cassert>
#include <random>
#include <set>

struct Cube {
	int x, y, z, size;
	int intersect_area(const Cube& that) const {
		const auto height = std::min(x + size, that.x + size) - std::max(x, that.x);
		const auto width = std::min(y + size, that.y + size) - std::max(y, that.y);
		const auto depth = std::min(z + size, that.z + size) - std::max(z, that.z);
		if (height <= 0 || width <= 0 || depth <= 0) return 0;
		return (height * width + width * depth + depth * height) * 2;
	}
};
int main() {
	while (true) {
		int n, k, s; std::cin >> n >> k >> s; if (n == 0 && k == 0 && s == 0) break;
		std::vector<Cube> cubes(n); for (auto& c : cubes) {
			std::cin >> c.x >> c.y >> c.z;
			c.size = s;
		}
		if (k == 1) {
			std::cout << s * s * 6 << std::endl;
			continue;
		}
		std::vector<std::vector<int>> nodes(n);
		for (auto i = 0; i < n; ++i) {
			for (auto j = 0; j < i; ++j) {
				if (cubes[i].intersect_area(cubes[j]) > 0) {
					nodes[i].push_back(j);
					nodes[j].push_back(i);
				}
			}
		}
		std::vector<bool> searching(n, false);
		std::vector<Cube> temp;
		std::vector<int> sum;
		std::stack<int> stack;
		int max_reduce = -1;
		for (auto i = 0; i < n; ++i) if (!searching[i] && nodes[i].size() == 1) {
			temp.clear();
			stack.push(i);
			while (!stack.empty()) {
				const auto top = stack.top(); stack.pop();
				temp.push_back(cubes[top]);
				searching[top] = true;
				for (const auto next : nodes[top]) if (!searching[next]) {
					stack.push(next);
				}
			}
			if (temp.size() < k) continue;
			sum.clear(); sum.push_back(0);
			for (auto j = 1; j < temp.size(); ++j) {
				sum.push_back(sum.back() + temp[j].intersect_area(temp[j - 1]));
			}
			for (auto j = k - 1; j < temp.size(); ++j) {
				max_reduce = std::max(max_reduce, sum[j] - sum[j - k + 1]);
			}
		}
		for (auto i = 0; i < n; ++i) if (!searching[i] && nodes[i].size() == 2) {
			temp.clear();
			temp.push_back(cubes[i]);
			searching[i] = true;
			stack.push(nodes[i].front());
			while (!stack.empty()) {
				const auto top = stack.top(); stack.pop();
				temp.push_back(cubes[top]);
				searching[top] = true;
				for (const auto next : nodes[top]) if (!searching[next]) {
					stack.push(next);
				}
			}
			if (temp.size() < k) continue;
			sum.clear(); sum.push_back(0);
			for (auto j = 1; j < temp.size(); ++j) {
				sum.push_back(sum.back() + temp[j].intersect_area(temp[j - 1]));
			}
			sum.push_back(sum.back() + temp.front().intersect_area(temp.back()));
			if (temp.size() == k) {
				max_reduce = std::max(max_reduce, sum.back());
				continue;
			}
			for (auto j = 1; j < temp.size(); ++j) {
				sum.push_back(sum.back() + temp[j].intersect_area(temp[j - 1]));
			}
			for (auto j = k - 1; j < sum.size(); ++j) {
				max_reduce = std::max(max_reduce, sum[j] - sum[j - k + 1]);
			}
		}
		if (max_reduce == -1) {
			std::cout << -1 << std::endl;
		}
		else {
			std::cout << k * s * s * 6 - max_reduce << std::endl;
		}
	}
}



Measured memory_bytes: 3104