数字键盘锁 dfs

总时间限制:
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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值