总时间限制:
1000ms
内存限制:
65536kB
-
描述
-
几乎所有的安卓智能手机都有九宫格键盘锁,如下图1所示。从随机的一个点开始,按一定顺序依次向不同的点划动,可以形成一条路径,以达到加锁和解锁手机的目的。现在把键盘锁抽象成下图2所示3*3的矩阵,把每个点用数字来表示。
图1 键盘锁
图2 编号示意
一个数字键盘锁的合法性描述如下:
1.一个合法的手势图案,由一串数字组成,这串数字只记录每个点第一次被触碰到时的顺序。我们把这串数字称为手势数字,把触碰过的点称为激活点;
2.在手势数字中,两个相邻的数字必须可以直接相连,或者经过激活点相连;否则,这个手势数字就是不合法的。
现在给出九宫格键盘锁要使用到的N个数字点,要求每个数字点都要被使用到,求有多少种合法的手势数字。
输入
-
第一行一个正整数K(1≤K≤10)表示之后有K组数据。
之后每组数据占2行,第1行一个正整数N(3≤N≤9),第2行N个互不相同的正整数Num 1,Num 2,...Num N(1≤Num≤9)表示将在键盘锁中使用到的N个数字。
输出
- 对应每组输入数据,输出一个正整数,代表有多少合法的手势数字。 样例输入
-
231 2 441 2 3 9
样例输出
-
62
提示
-
对于第二个样例,只有9→2→1→3和9→2→3→1两组合法的手势。
#include <cstdio> #define my_abs(x) (((x)>=0)?(x):(-(x))) bool num[10]; bool used[10]; bool REACH( int a, int b ) { if ( (a==0) || (b==0) ) return true; if ( (my_abs(((a-1)/3)-((b-1)/3))==1) || (my_abs(((a-1)%3)-((b-1)%3))==1) ) return true; return ( used[(a+b)>>1] ); } int DFS( int depth, int u ) { if ( depth <= 0 ) return 1; int ret = 0; for ( int v=1; v<=9; v++ ) { if ( num[v] && REACH(u,v) ) { num[v] = 0; used[v] = 1; ret += DFS( depth-1, v ); num[v] = 1; used[v] = 0; } } return ret; } int main() { int t, n, tmp; // freopen( "in2.in", "r", stdin ); // freopen( "YYC2.out", "w", stdout ); scanf( "%d", &t ); for ( int cas=1; cas<=t; cas++ ) { for ( int i=1; i<=9; i++ ) { num[i] = 0; used[i] = 0; } scanf( "%d", &n ); for ( int i=0; i<n; i++ ) { scanf( "%d", &tmp ); num[tmp] = 1; } //printf( "case %d: %d\n", cas, DFS( n, 0 ) ); printf( "%d\n", DFS( n, 0 ) ); } return 0; }