详细分析见滑动解锁分析
AC代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 10 + 5;
int vis[maxn], ans, n, G[maxn][maxn], e[maxn][maxn];
struct edge{
int x, y;
}a[maxn];
void init() {
memset(G, 0, sizeof(G));
for(int i = 1; i <= 7; i+=3)
G[i][i+2] = G[i+2][i] = i+1;
for(int i = 1; i <= 3; ++i)
G[i][i+6] = G[i+6][i] = i+3;
G[1][9] = G[9][1] = G[3][7] = G[7][3] = 5;
}
void dfs(int u, int cnt) {
//is it possible
for(int i = 0; i < n; ++i) {
int x = a[i].x, y = a[i].y;
if(vis[x] && vis[y] && !e[x][y] && !e[y][x]) return; //一条边的两个端点都被使用,但是这条边没使用则剪枝
}
int flag = 1;
for(int i = 0; i < n; ++i) {
if(!e[a[i].x][a[i].y] && !e[a[i].y][a[i].x]) {
flag = 0;
break;
}
}
if(flag && cnt >= 4) ans++;
for(int i = 1; i <= 9; ++i) {
if(u != i && !vis[i] && vis[G[u][i]]) {
vis[i] = e[u][i] = 1;
dfs(i, cnt+1);
vis[i] = e[u][i] = 0;
}
}
}
int main() {
init();
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 0; i < n; ++i) scanf("%d%d", &a[i].x, &a[i].y);
ans = 0;
for(int i = 1; i <= 9; ++i) {
memset(vis, 0, sizeof(vis));
memset(e, 0, sizeof(e));
vis[0] = vis[i] = 1;
dfs(i, 1);
}
printf("%d\n", ans);
}
return 0;
}
如有不当之处欢迎指出!