详细分析见滑动解锁分析
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; }
如有不当之处欢迎指出!