经典的状态压缩dp每个格子分三种状态(下面的格子为当前格),如图所示,分别用0,1,2表示
然后利用上一行的合法状态推导出当前行的一个基本状态(黑书上有详解),在该基本状态上,枚举可能的方案,更新表格
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::greater;
using std::endl;
const int INFI((INT_MAX-1) >> 1);
const int MAXN(160);
const int MAXM(11);
bool mp[MAXN][MAXM];
int table[2][60000];
int pow3[12];
int N, M, K;
int cur, last;
int as1[11], as2[11];
void updata(int n, int st1, int &st2)
{
st2 = 0;
for(int i = 0; i < M; ++i)
{
as1[i] = st1%3;
if(mp[n][i])
{
if(as1[i] == 2)
{
as2[i] = 1;
st2 += 1*pow3[i];
}
else
{
as2[i] = 0;
st2 += 0;
}
}
else
{
as2[i] = 2;
st2 += 2*pow3[i];
}
st1 /= 3;
}
}
void dfs(int n, int m, int st, int value)
{
if(value > table[cur][st])
table[cur][st] = value;
if(m <= M-2 && as2[m] == 0 && as2[m+1] == 0 && as1[m] == 0 && as1[m+1] == 0)
{
as2[m] = 2;
as2[m+1] = 2;
dfs(n, m+2, st+pow3[m]*2+pow3[m+1]*2, value+1);
as2[m] = 0;
as2[m+1] = 0;
}
if(m <= M-3 && as2[m] == 0 && as2[m+1] == 0 && as2[m+2] == 0)
{
as2[m] = 2;
as2[m+1] = 2;
as2[m+2] = 2;
dfs(n, m+3, st+pow3[m]*2+pow3[m+1]*2+pow3[m+2]*2, value+1);
as2[m] = 0;
as2[m+1] = 0;
as2[m+2] = 0;
}
if(m <= M-1)
dfs(n, m+1, st, value);
}
int main()
{
pow3[0] = 1;
for(int i = 1; i <= 11; ++i)
pow3[i] = pow3[i-1]*3;
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d%d", &N, &M, &K);
memset(mp, 0, sizeof(mp));
for(int i = 1; i <= N; ++i)
for(int j = 0; j < M; ++j)
mp[i][j] = true;
int x, y;
for(int i = 0; i < K; ++i)
{
scanf("%d%d", &x, &y);
mp[x][y-1] = false;
}
cur = 0;
last = 1;
memset(table[last], -1, sizeof(table[last]));
int temp = 0;
for(int i = 0; i < M; ++i)
if(mp[1][i])
temp += pow3[i]*1;
else
temp += pow3[i]*2;
table[last][temp] = 0;
for(int i = 2; i <= N; ++i)
{
memset(table[cur], -1, sizeof(table[cur]));
for(int j = 0; j < pow3[M]; ++j)
if(table[last][j] != -1)
{
int st2;
updata(i, j, st2);
dfs(i, 0, st2, table[last][j]);
}
cur ^= 1;
last ^= 1;
}
int ans = 0;
for(int i = 0; i < pow3[M]; ++i)
if(table[last][i] > ans)
ans = table[last][i];
printf("%d\n", ans);
}
return 0;
}