#include "bits/stdc++.h"
#ifdef LOCAL
#include "debug.h"
#else
#define dbg(...)
#define dprint(...)
#define debug if constexpr (false)
#define draw_tree(...)
#define draw_array(...)
#endif // LOCAL
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep1(i, n) for (int i = 1; i < (n); ++i)
#define rep1n(i, n) for (int i = 1; i <= (n); ++i)
#define repr(i, n) for (int i = (n) - 1; i >= 0; --i)
#define pb push_back
#define eb emplace_back
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define each(x, a) for (auto &x : a)
#define ar array
#define vec vector
#define range(i, n) rep(i, n)
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using str = string;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
using vpi = vector<pair<int, int>>;
using vvi = vector<vi>;
int Bit(int mask, int b) { return (mask >> b) & 1; }
template<class T>
bool ckmin(T &a, const T &b) {
if (b < a) {
a = b;
return true;
}
return false;
}
template<class T>
bool ckmax(T &a, const T &b) {
if (b > a) {
a = b;
return true;
}
return false;
}
// [l, r)
template<typename T, typename F>
T FindFirstTrue(T l, T r, const F &predicat) {
--l;
while (r - l > 1) {
T mid = l + (r - l) / 2;
if (predicat(mid)) {
r = mid;
} else {
l = mid;
}
}
return r;
}
template<typename T, typename F>
T FindLastFalse(T l, T r, const F &predicat) {
return FindFirstTrue(l, r, predicat) - 1;
}
const ll INF = 2e18;
const int INFi = 2e9;
bool Equal(ll A, ll B) {
return A == B;
}
bool Less(ll A, ll B) {
return A < B;
}
bool Greater(ll A, ll B) {
return A > B;
}
bool LessOrEqual(ll A, ll B) {
return A <= B;
}
bool GreaterOrEqual(ll A, ll B) {
return A >= B;
}
const ld EPS = 1e-9;
bool Equal(ld A, ld B) {
return abs(A - B) < EPS;
}
bool Less(ld A, ld B) {
return A + EPS < B;
}
bool Greater(ld A, ld B) {
return A > B + EPS;
}
bool LessOrEqual(ld A, ld B) {
return A <= B + EPS;
}
bool GreaterOrEqual(ld A, ld B) {
return A + EPS >= B;
}
template<typename T, typename Q>
bool LessOrEqual(T A, Q B) {
using C = std::common_type_t<T, Q>;
return LessOrEqual(static_cast<C>(A), static_cast<C>(B));
}
template<typename T, typename Q>
bool Equal(T A, Q B) {
using C = std::common_type_t<T, Q>;
return Equal(static_cast<C>(A), static_cast<C>(B));
}
template<typename T, typename Q>
bool Less(T A, Q B) {
using C = std::common_type_t<T, Q>;
return Less(static_cast<C>(A), static_cast<C>(B));
}
template<typename T, typename Q>
bool Greater(T A, Q B) {
using C = std::common_type_t<T, Q>;
return Greater(static_cast<C>(A), static_cast<C>(B));
}
template<typename T, typename Q>
bool GreaterOrEqual(T A, Q B) {
using C = std::common_type_t<T, Q>;
return GreaterOrEqual(static_cast<C>(A), static_cast<C>(B));
}
template<typename T>
ll sgn(T x) {
if (Equal(x, 0)) return 0;
return Less(x, 0) ? -1 : 1;
}
template<typename T>
struct Point {
T x;
T y;
Point(T x_ = 0, T y_ = 0) : x(x_), y(y_) {}
template<typename Q>
Point(const Point<Q> &other) {
x = static_cast<T>(other.x);
y = static_cast<T>(other.y);
}
template<typename Q>
Point(Point<Q> &&other) {
x = static_cast<T>(other.x);
y = static_cast<T>(other.y);
}
template<typename Q>
Point<std::common_type_t<T, Q>> operator+(const Point<Q> &oth) const {
return Point{x + oth.x, y + oth.y};
}
template<typename Q>
Point<std::common_type_t<T, Q>> operator-(const Point<Q> &oth) const {
return {x - oth.x, y - oth.y};
}
template<typename Q>
bool operator==(const Point<Q> &oth) const {
return x == oth.x && y == oth.y;
}
template<typename Q>
bool operator<(const Point<Q> &oth) const {
return make_pair(x, y) < make_pair(oth.x, oth.y);
}
template<typename Q>
requires (is_integral_v<Q> || is_floating_point_v<Q>)
Point<std::common_type_t<Q, T>> operator*(const Q &b) const {
return {x * b, y * b};
}
template<typename Q>
requires (is_integral_v<Q> || is_floating_point_v<Q>)
Point<ld> operator/(const Q &b) const {
return {(ld) x / b, (ld) y / b};
}
template<typename Q>
std::common_type_t<Q, T> operator*(const Point<Q> &oth) const {
return x * oth.y - y * oth.x;
}
template<typename Q>
std::common_type_t<Q, T> operator%(const Point<Q> &oth) const {
return x * oth.x + y * oth.y;
}
Point &operator+=(const Point &other) {
x += other.x;
y += other.y;
return *this;
}
Point &operator-=(const Point &other) {
x -= other.x;
y -= other.y;
return *this;
}
friend ostream &operator<<(ostream &stream, const Point &P) {
stream << P.x << ' ' << P.y;
return stream;
}
friend istream &operator>>(istream &stream, Point &P) {
stream >> P.x >> P.y;
return stream;
}
};
template<typename T>
Point<T> rotateCW(const Point<T> &P) {
return {P.y, -P.x};
}
template<typename T>
Point<T> rotateCCW(const Point<T> &P) {
return {-P.y, P.x};
}
template<typename T, typename Q>
bool Equal(const Point<T> &a, const Point<Q> &b) {
return Equal(a.x, b.x) && Equal(a.y, b.y);
}
template<typename T, typename Q>
bool Less(const Point<T> &a, const Point<Q> &b) {
if (!Equal(a.x, b.x)) return Less(a.y, b.y);
return Less(a.y, b.y);
}
template<typename T, typename Q>
bool Greater(const Point<T> &a, const Point<Q> &b) {
if (!Equal(a.x, b.x)) return Greater(a.y, b.y);
return Greater(a.y, b.y);
}
template<typename T>
Point<T> operator-(const Point<T> &a) {
return {-a.x, -a.y};
}
template<typename T>
T len2(const Point<T> &a) {
return a % a;
}
template<typename T>
ld len(const Point<T> &a) {
return sqrtl(len2(a));
}
template<typename T, typename Q>
T dist2(const Point<T> &a, const Point<Q> &b) {
return len2(a - b);
}
template<typename T, typename Q>
ld dist(const Point<T> &a, const Point<Q> &b) {
return len(a - b);
}
using pt = Point<ll>;
template<typename T, typename U>
bool VComp(const Point<T> &a, const Point<U> &b) {
bool upA = a.y > 0 || (a.y == 0 && a.x >= 0);
bool upB = b.y > 0 || (b.y == 0 && b.x >= 0);
if (upA != upB) return upA;
auto val = a * b;
if (val != 0) return val > 0;
return len2(a) < len2(b);
}
template<typename T, typename U>
bool VCompNoLen(const Point<T> &a, const Point<U> &b) {
bool upA = a.y > 0 || (a.y == 0 && a.x >= 0);
bool upB = b.y > 0 || (b.y == 0 && b.x >= 0);
if (upA != upB) return upA;
auto val = a * b;
return val > 0;
}
const int LG = 18;
const int N = 1 << LG;
pair<ll, ll> dp[N][LG];
bool valid[LG][LG][LG];
void add(int i, int j, pair<ll, ll> ways, ll cost) {
ways.first += cost;
if (dp[i][j].first < ways.first) return;
if (dp[i][j].first > ways.first) {
dp[i][j].first = ways.first;
dp[i][j].second = 0;
}
dp[i][j].second += ways.second;
}
int GetBit(int mask, int b) {
return (mask >> b) & 1;
}
vector<pt> a;
vector<vl> w;
int n;
vi was;
pair<ll, ll> solve(int mask, int b) {
if (dp[mask][b].second != -1) return dp[mask][b];
was.push_back(mask);
dp[mask][b].second = 0;
int pr = b - 1;
int nx = b + 1;
while (pr >= 0 && !GetBit(mask, pr)) pr--;
while (nx < n && !GetBit(mask, nx)) nx++;
if (nx != n) {
add(mask, b, solve(mask, nx), 0);
for(int t = b + 1; t < nx; ++t) {
if (valid[b][t][nx] && (a[nx] - a[b]) * (a[t] - a[b]) > 0) {
add(mask, b, solve(mask ^ (1 << t), b), w[t][nx] + w[t][b]);
dbg(mask, b, dp[mask][b], t);
}
}
if (pr != -1) {
if (valid[pr][b][nx] && (a[b] - a[pr]) * (a[nx] - a[pr]) > 0) {
add(mask, b, solve(mask ^ (1 << b), pr), w[pr][nx]);
dbg(mask, b, dp[mask][b], -1);
}
}
}
dbg(mask, b, dp[mask][b]);
return dp[mask][b];
}
template<typename T>
bool inside(Point<T> a, Point<T> b, Point<T> c, Point<T> d) {
auto area = [&](auto v1, auto v2) {
return abs(v1 * v2);
};
return area(b - a, c - a) == area(a - d, b - d) + area(b - d, c - d) + area(c - d, a - d);
}
void solve() {
cin >> n;
a.resize(n);
rep(i, n) cin >> a[i];
w.assign(n, vl(n));
rep(i, n) {
rep(j, n) {
cin >> w[i][j];
}
}
{
vi ord(n);
iota(all(ord), 0);
sort(all(ord), [&](const int &i, const int &j) { return a[i] < a[j]; });
vector<pt> b(n);
rep(i, n) b[i] = a[ord[i]];
vector<vl> ww(n, vl(n));
rep(i, n) {
rep(j, n) {
ww[i][j] = w[ord[i]][ord[j]];
}
}
swap(a, b);
swap(w, ww);
}
memset(valid, 0, sizeof(valid));
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
for (int k = j + 1; k < n; k++) {
bool ok = true;
for (int x = 0; x < n; x++) {
if (x == i || x == j || x == k) {
continue;
}
if (inside(a[i], a[j], a[k], a[x])) {
ok = false;
break;
}
}
valid[i][j][k] = ok;
}
}
}
{
vi stk;
stk.push_back(0);
for (int i = 1; i < n; ++i) {
while (stk.size() >= 2 &&
(a[stk[stk.size() - 1]] - a[stk[stk.size() - 2]]) * (a[i] - a[stk[stk.size() - 2]]) > 0) {
stk.pop_back();
}
stk.push_back(i);
}
int mask = 0;
for (auto &i: stk) mask |= (1 << i);
dp[mask][n - 1] = {0, 1};
was.push_back(mask);
}
{
vi stk;
stk.push_back(0);
for (int i = 1; i < n; ++i) {
while (stk.size() >= 2 &&
(a[stk[stk.size() - 1]] - a[stk[stk.size() - 2]]) * (a[i] - a[stk[stk.size() - 2]]) < 0) {
stk.pop_back();
}
stk.push_back(i);
}
int mask = 0;
for (auto &i: stk) mask |= (1 << i);
ll res = 0;
for(int i = 1; i < stk.size(); ++i) res += w[stk[i - 1]][stk[i]];
auto ans = solve(mask, 0);
ans.first += res;
cout << ans.first << ' ' << ans.second << '\n';
}
for(auto &mask : was) {
rep(i, n) dp[mask][i] = {INF, -1};
}
was.clear();
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(12) << fixed;
int t = 1;
rep(i, N) rep(j, LG) dp[i][j] = {INF, -1};
cin >> t;
rep(i, t) {
solve();
}
return 0;
}