// Author: kyEEcccccc
#pragma GCC optimize(2)
#pragma G++ optimize(2)
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using ULL = unsigned long long;
int n, m, k;
bool a[150][20];
int pw[20];
int f[60000], mx[60000];
int must[20], block[20];
vector<int> fre;
int at(int stt, int j)
{
return stt / pw[j] % 3;
}
int at2(int stt, int j)
{
return (stt >> j) & 1;
}
void init(void)
{
for (int stt = 0; stt < pw[m]; ++stt)
f[stt] = INT_MIN/2;
int ini = 0;
for (int j = 0; j < m; ++j)
if (a[0][j] == 1) ini += pw[j]*2;
else ini += pw[j];
f[ini] = 0;
for (int stt = 0; stt < pw[m]; ++stt)
mx[stt] = f[stt];
for (int j = 0; j < m; ++j)
{
for (int stt = 0; stt < pw[m]; ++stt)
if (at(stt, j) == 1)
mx[stt] = max(mx[stt], mx[stt-pw[j]]);
for (int stt = 0; stt < pw[m]; ++stt)
if (at(stt, j) == 2)
mx[stt] = max(mx[stt], mx[stt-pw[j]]);
}
}
bool checkput(int i, int put)
{
if (at(put, 0) != 0) return 0;
if (at(put, 1) == 1) return 0;
if (i == 1)
{
for (int j = 0; j < m; ++j)
if (at(put, j) == 2) return 0;
}
for (int j = 0; j < m; ++j)
{
if (at(put, j) == 1 && (a[i][j] || a[i-1][j] || a[i][j-1]
|| a[i-1][j-1] || a[i][j-2] || a[i-1][j-2]))
return 0;
if (at(put, j) == 2 && (a[i][j] || a[i-1][j] || a[i-2][j]
|| a[i][j-1] || a[i-1][j-1] || a[i-2][j-1]))
return 0;
}
for (int j = 2; j < m; ++j)
{
if (at(put, j) == 1
&& (at(put, j-1) != 0 || at(put, j-2) != 0))
return 0;
if (at(put, j) == 2 && at(put, j-1) != 0)
return 0;
}
return 1;
}
int getans(void)
{
int mx = INT_MIN/2;
for (int stt = 0; stt < pw[m]; ++stt)
mx = max(mx, f[stt]);
return mx;
}
void solve(void)
{
for (int i = 1; i < n; ++i)
{
// cerr << "i: " << i << '\n';
for (int stt = 0; stt < pw[m]; ++stt)
f[stt] = INT_MIN/2;
for (int put = 0; put < pw[m]; ++put)
{
if (!checkput(i, put)) continue;
// cerr << "put: " << put << '\n';
for (int j = 0; j < m; ++j)
must[j] = 2;
for (int j = 0; j < m; ++j)
{
if (at(put, j) == 1)
{
must[j] = min(must[j], 1);
must[j-1] = min(must[j-1], 1);
must[j-2] = min(must[j-2], 1);
}
if (at(put, j) == 2)
{
must[j] = min(must[j], 0);
must[j-1] = min(must[j-1], 0);
}
}
int tot = 0;
for (int j = 0; j < m; ++j)
if (at(put, j) != 0) ++tot;
fre.clear();
for (int j = 0; j < m; ++j)
if (must[j] == 2) fre.push_back(j);
for (int cha = 0; cha < (1 << fre.size()); ++cha)
{
for (int l = 0; l < fre.size(); ++l)
if (at2(cha, l) == 1) must[fre[l]] = 1;
int from = 0;
for (int j = 0; j < m; ++j)
from += must[j]*pw[j];
int curres = mx[from] + tot;
for (int j = 0; j < m; ++j)
{
if (a[i][j]) block[j] = 2;
else if (a[i-1][j]) block[j] = 1;
else block[j] = 0;
}
for (int j = 0; j < m; ++j)
if (must[j] == 2) block[j] = max(block[j], 1);
for (int j = 0; j < m; ++j)
{
if (at(put, j) == 1)
block[j] = block[j-1] = block[j-2] = 2;
if (at(put, j) == 2)
block[j] = block[j-1] = 2;
}
int to = 0;
for (int j = 0; j < m; ++j)
to += block[j]*pw[j];
// if (curres >= 0)
// cerr << from << ' ' << to << ' ' << curres << '\n';
f[to] = max(f[to], curres);
for (int l = 0; l < fre.size(); ++l)
must[fre[l]] = 2;
}
}
// cerr << pw[m] << endl;
// for (int stt = 0; stt < pw[m]; ++stt)
// if (f[stt] >= 0)
// cerr << stt << " - " << f[stt] << '\n';
for (int stt = 0; stt < pw[m]; ++stt)
mx[stt] = f[stt];
for (int j = 0; j < m; ++j)
{
for (int stt = 0; stt < pw[m]; ++stt)
if (at(stt, j) == 1)
mx[stt] = max(mx[stt], mx[stt-pw[j]]);
for (int stt = 0; stt < pw[m]; ++stt)
if (at(stt, j) == 2)
mx[stt] = max(mx[stt], mx[stt-pw[j]]);
}
// cerr << getans() << '\n';
}
}
void work(void)
{
cin >> n >> m >> k;
memset(a, 0, sizeof (a));
for (int i = 1; i <= k; ++i)
{
int x, y;
cin >> x >> y;
a[x-1][y-1] = 1;
}
init();
solve();
cout << getans() << '\n';
}
int main(void)
{
// freopen("i.txt", "r", stdin);
ios::sync_with_stdio(0);
cin.tie(NULL);
pw[0] = 1;
for (int i = 1; i <= 10; ++i)
pw[i] = pw[i-1] * 3;
int tsk;
cin >> tsk;
while (tsk--) work();
return 0;
}
复杂度有点玄学,不过本来就玄学题,150*10的图开O2跑0.97s,AcWing上G飞了。求大佬帮卡。