详细分析见滑动解锁分析

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;
}

如有不当之处欢迎指出!

04-27 16:26