Pattern lock security is generally used in Android handsets instead of a password. The pattern lock can be set by joining points on a 3 × 3 matrix in a chosen order. The points of the matrix are registered in a numbered order starting with 1 in the upper left corner and ending with 9 in the bottom right corner.
A valid pattern has the following properties:
Now you are given n active points, you need to find the number of valid pattern locks formed from those active points.
There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:
The first line contains an integer n (3 ≤ n ≤ 9), indicating the number of active points. The second line contains n distinct integers a1, a2, … an (1 ≤ ai ≤ 9) which denotes the identifier of the active points.
For each test case, print a line containing an integer m, indicating the number of valid pattern lock.
In the next m lines, each contains n integers, indicating an valid pattern lock sequence. The m sequences should be listed in lexicographical order.
1 3 1 2 3
4 1 2 3 2 1 3 2 3 1 3 2 1
Author: LIN, Xi
Source: The 15th Zhejiang University Programming Contest
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int n,x; const int MAX = 500000; int ans[11],res[MAX][11],a[11],vis[11]; bool ok(int m) { int flag[11]; for(int i = 0 ; i <= 10; i++) flag[i] = 0; for(int i = 1; i <= n ; i++) { flag[res[m][i]] = 1; if((res[m][i] == 1 && res[m][i+1] == 9 && flag[5] == 0)|| (res[m][i] == 9 && res[m][i+1] == 1 && flag[5] == 0) || (res[m][i] == 1 && res[m][i+1] == 3 && flag[2] == 0)|| (res[m][i] == 3 && res[m][i+1] == 1 && flag[2] == 0) || (res[m][i] == 1 && res[m][i+1] == 7 && flag[4] == 0)|| (res[m][i] == 7 && res[m][i+1] == 1 && flag[4] == 0) || (res[m][i] == 2 && res[m][i+1] == 8 && flag[5] == 0)|| (res[m][i] == 8 && res[m][i+1] == 2 && flag[5] == 0) || (res[m][i] == 4 && res[m][i+1] == 6 && flag[5] == 0)|| (res[m][i] == 6 && res[m][i+1] == 4 && flag[5] == 0) || (res[m][i] == 3 && res[m][i+1] == 9 && flag[6] == 0)|| (res[m][i] == 9 && res[m][i+1] == 3 && flag[6] == 0) || (res[m][i] == 7 && res[m][i+1] == 9 && flag[8] == 0)|| (res[m][i] == 9 && res[m][i+1] == 7 && flag[8] == 0) || (res[m][i] == 3 && res[m][i+1] == 7 && flag[5] == 0)|| (res[m][i] == 7 && res[m][i+1] == 3 && flag[5] == 0) ) return 0; } return 1; } void DFS(int cnt) { if(cnt == n + 1) { x++; for(int i = 1; i <= n ; i++) res[x][i] = ans[i]; return ; } for(int i = 1; i <= n; i++) { if(!vis[a[i]]) { ans[cnt] = a[i]; vis[a[i]] = 1; DFS(cnt+1); vis[a[i]] = 0; } } } int main() { int T; scanf("%d",&T); while(T--) { memset(res, -1, sizeof(res)); scanf("%d",&n); for(int i = 1; i <= n ; i++) scanf("%d",&a[i]); sort(a+1,a+n+1); x = 0; memset(vis, false, sizeof(vis)); DFS(1); int temp = x; for(int i = 1; i <= temp; i++) { if(ok(i) == 0) x--; } printf("%d\n",x); for(int i = 1; i <= temp ; i++) { if(ok(i)) { for(int j = 1; j < n ; j++) printf("%d ",res[i][j]); printf("%d\n",res[i][n]); } } } return 0; }
主要是全排列的算法:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAX = 500000; int n,x; int a[11],ans[11],res[MAX][11],vis[11]; void DFS(int cnt) { if(cnt == n + 1){ x++; for(int i = 1; i <= n ; i++) res[x][i] = ans[i]; return ; } for(int i = 1; i <= n; i++){ if(!vis[i]){//用vis[i]或者vis[a[i]]要看数的大小,因为遍历的是数的个数,如果数很大那么这个循环明显不够 ans[cnt] = a[i]; vis[i] = 1; DFS(cnt+1); vis[i] = 0; } } } int main() { int T; scanf("%d",&T); while(T--){ scanf("%d",&n); memset(res,-1,sizeof(res)); memset(vis,0,sizeof(vis)); for(int i = 1; i <= n ;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); x = 0; DFS(1); printf("%d\n",x); for(int i = 1; i <= x; i++){ for(int j = 1 ; j < n ;j++) printf("%d ",res[i][j]); printf("%d\n",res[i][n]); } } return 0; }