#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ll long long
#define all(name) name.begin(),name.end()
#define rall(name) name.rbegin(),name.rend()
#define sz(s) (int)s.size()
int dx[]{1, -1, 0, 0, 1, 1, -1, -1};
int dy[]{0, 0, 1, -1, 1, -1, 1, -1};
void fast() {
std::ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll n, m;
vector<vector<ll>> v;
ll vis[40][40][40][40];
struct node {
ll x, y, sx, sy, d;
};
bool valid(node t) {
return (t.x >= 0 && t.x < n && t.y >= 0 && t.y < m &&
abs(t.sx) < 4 && abs(t.sy) < 4 && v[t.x][t.y] &&
!vis[t.x][t.y][t.sx + 3][t.sy + 3]);
}
void solve() {
cin >> n >> m;
v.resize(n + 2, vector<ll>(m + 2, 1LL));
memset(vis, 0, sizeof(vis));
pair<ll, ll> s, t;
ll p, x1, x2, y1, y2;
cin >> s.first >> s.second >> t.first >> t.second >> p;
while (p--) {
cin >> x1 >> x2 >> y1 >> y2;
for (int i = x1; i <= x2; i++)
for (int j = y1; j <= y2; j++)
v[i][j] = 0;
}
ll ans = -1, tsx, tsy, tx, ty;
queue<node> q;
q.push({s.first, s.second, 0, 0, 0});
while (!q.empty()) {
node pp = q.front();
q.pop();
if (t == make_pair(pp.x, pp.y)) {
ans = pp.d;
break;
}
for (int i = 0; i < 9; i++) {
tsx = pp.sx + dx[i];
tsy = pp.sy + dy[i];
tx = pp.x + tsx;
ty = pp.y + tsy;
node temp = {tx, ty, tsx, tsy, pp.d + 1};
if (valid(temp)) {
vis[tx][ty][tsx + 3][tsy + 3] = 1;
q.push(temp);
}
}
}
if (ans == -1)
cout << "No solution.\n";
else
cout << "Optimal solution takes " << ans << " hops.\n";
}
int main() {
fast();
int T = 1;
cin >> T;
while (T--) {
solve();
}
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CnR5cGVkZWYgbG9uZyBsb25nIGxsOwojZGVmaW5lIGxsIGxvbmcgbG9uZwojZGVmaW5lIGFsbChuYW1lKSAgbmFtZS5iZWdpbigpLG5hbWUuZW5kKCkKI2RlZmluZSByYWxsKG5hbWUpICBuYW1lLnJiZWdpbigpLG5hbWUucmVuZCgpCiNkZWZpbmUgc3oocykgKGludClzLnNpemUoKQppbnQgZHhbXXsxLCAtMSwgMCwgMCwgMSwgMSwgLTEsIC0xfTsKaW50IGR5W117MCwgMCwgMSwgLTEsIDEsIC0xLCAxLCAtMX07Cgp2b2lkIGZhc3QoKSB7CiAgICBzdGQ6Omlvc19iYXNlOjpzeW5jX3dpdGhfc3RkaW8oMCk7CiAgICBjaW4udGllKDApOwogICAgY291dC50aWUoMCk7Cn0KCmxsIG4sIG07CnZlY3Rvcjx2ZWN0b3I8bGw+PiB2OwpsbCB2aXNbNDBdWzQwXVs0MF1bNDBdOwpzdHJ1Y3Qgbm9kZSB7CiAgICBsbCB4LCB5LCBzeCwgc3ksIGQ7Cn07Cgpib29sIHZhbGlkKG5vZGUgdCkgewogICAgcmV0dXJuICh0LnggPj0gMCAmJiB0LnggPCBuICYmIHQueSA+PSAwICYmIHQueSA8IG0gJiYKICAgICAgICAgICAgYWJzKHQuc3gpIDwgNCAmJiBhYnModC5zeSkgPCA0ICYmIHZbdC54XVt0LnldICYmCiAgICAgICAgICAgICF2aXNbdC54XVt0LnldW3Quc3ggKyAzXVt0LnN5ICsgM10pOwp9Cgp2b2lkIHNvbHZlKCkgewogICAgY2luID4+IG4gPj4gbTsKICAgIHYucmVzaXplKG4gKyAyLCB2ZWN0b3I8bGw+KG0gKyAyLCAxTEwpKTsKICAgIG1lbXNldCh2aXMsIDAsIHNpemVvZih2aXMpKTsKICAgIHBhaXI8bGwsIGxsPiBzLCB0OwogICAgbGwgcCwgeDEsIHgyLCB5MSwgeTI7CiAgICBjaW4gPj4gcy5maXJzdCA+PiBzLnNlY29uZCA+PiB0LmZpcnN0ID4+IHQuc2Vjb25kID4+IHA7CiAgICB3aGlsZSAocC0tKSB7CiAgICAgICAgY2luID4+IHgxID4+IHgyID4+IHkxID4+IHkyOwogICAgICAgIGZvciAoaW50IGkgPSB4MTsgaSA8PSB4MjsgaSsrKQogICAgICAgICAgICBmb3IgKGludCBqID0geTE7IGogPD0geTI7IGorKykKICAgICAgICAgICAgICAgIHZbaV1bal0gPSAwOwogICAgfQogICAgbGwgYW5zID0gLTEsIHRzeCwgdHN5LCB0eCwgdHk7CiAgICBxdWV1ZTxub2RlPiBxOwogICAgcS5wdXNoKHtzLmZpcnN0LCBzLnNlY29uZCwgMCwgMCwgMH0pOwogICAgd2hpbGUgKCFxLmVtcHR5KCkpIHsKICAgICAgICBub2RlIHBwID0gcS5mcm9udCgpOwogICAgICAgIHEucG9wKCk7CiAgICAgICAgaWYgKHQgPT0gbWFrZV9wYWlyKHBwLngsIHBwLnkpKSB7CiAgICAgICAgICAgIGFucyA9IHBwLmQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IDk7IGkrKykgewogICAgICAgICAgICB0c3ggPSBwcC5zeCArIGR4W2ldOwogICAgICAgICAgICB0c3kgPSBwcC5zeSArIGR5W2ldOwogICAgICAgICAgICB0eCA9IHBwLnggKyB0c3g7CiAgICAgICAgICAgIHR5ID0gcHAueSArIHRzeTsKICAgICAgICAgICAgbm9kZSB0ZW1wID0ge3R4LCB0eSwgdHN4LCB0c3ksIHBwLmQgKyAxfTsKICAgICAgICAgICAgaWYgKHZhbGlkKHRlbXApKSB7CiAgICAgICAgICAgICAgICB2aXNbdHhdW3R5XVt0c3ggKyAzXVt0c3kgKyAzXSA9IDE7CiAgICAgICAgICAgICAgICBxLnB1c2godGVtcCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICBpZiAoYW5zID09IC0xKQogICAgICAgIGNvdXQgPDwgIk5vIHNvbHV0aW9uLlxuIjsKICAgIGVsc2UKICAgICAgICBjb3V0IDw8ICJPcHRpbWFsIHNvbHV0aW9uIHRha2VzICIgPDwgYW5zIDw8ICIgaG9wcy5cbiI7Cn0KCmludCBtYWluKCkgewogICAgZmFzdCgpOwogICAgaW50IFQgPSAxOwogICAgY2luID4+IFQ7CiAgICB3aGlsZSAoVC0tKSB7CiAgICAgICAgc29sdmUoKTsKICAgIH0KICAgIHJldHVybiAwOwp9