ZOJ 3861 Valid Pattern Lock(level 1)(全排列暴力)

题目

Valid Pattern Lock


Time Limit: 2 Seconds      Memory Limit: 65536 KB


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.

valid_pattern_lock

A valid pattern has the following properties:

  • A pattern can be represented using the sequence of points which it's touching for the first time (in the same order of drawing the pattern). And we call those points as active points.
  • For every two consecutive points A and B in the pattern representation, if the line segment connecting A and B passes through some other points, these points must be in the sequence also and comes before A and B, otherwise the pattern will be invalid.
  • In the pattern representation we don't mention the same point more than once, even if the pattern will touch this point again through another valid segment, and each segment in the pattern must be going from a point to another point which the pattern didn't touch before and it might go through some points which already appeared in the pattern.

 

Now you are given n active points, you need to find the number of valid pattern locks formed from those active points.

Input

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.

Output

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.

Sample Input

1
3
1 2 3

Sample Output

4
1 2 3
2 1 3
2 3 1
3 2 1

 

 

题意:

这道题关键就是题意难以理解,如果你有题目中类似的手机锁屏的话,推荐你试一试就知道了。

给你n个数,然后是n个互不相同的数<=9,让你输出这n个数所能组成所有的锁屏路径序列

锁屏路径序列,就是路径上每经过一个还未被遍历到的点(称为激活),就记录下它,即只记录每一个点

第一次遍历到的时候的位置。

如果A,B是连续的,那么A,B 的路径上的点,都必须是已经被遍历过,且在A,B的顺序之前。

注意这里连续的两个点A,B一旦确定,他们的路径也是确定的。

譬如1,3,那么路径一定是1-(2)-3,即一定会经过2

4,3,7:4->3可以直接到达,3->7一定会经过5

然后序列每达到一个点,接下来一定是走向一个尚未被激活的点为目标

解析:

如果读懂了题意,其实就很好做了,用全排列暴力枚举,然后遍历数组相邻的两个点是否符合条件

这个限制条件其实也就只有8种:1-(2)-3,1-(4)-7,1-(5)-9,2-(5)-8,

3-(5)-7,3-(6)-9,4-(5)-6,7-(8)-9

#include <iostream>
#include<time.h>
#include<stdlib.h>
#include<cstdio>
#include<cstring>
#include <bitset>
#include <algorithm>
using namespace std;

const int N = 10;
const int maxn=5e5+10;

int a[N];
int vis[N];
int ans[maxn][N];

bool judge(int s,int e)
{
	if(s==1&&e==3||s==3&&e==1)
	{
		if(vis[2]) return true;
		else return false;
	}
	else if(s==1&&e==7||s==7&&e==1)
	{
		if(vis[4]) return true;
		else return false;
	}
	else if(s==1&&e==9||s==9&&e==1)
	{
		if(vis[5]) return true;
		else return false;
	}
	else if(s==2&&e==8||s==8&&e==2)
	{
		if(vis[5]) return true;
		else return false;
	}
	else if(s==3&&e==7||s==7&&e==3)
	{
		if(vis[5]) return true;
		else return false;
	}
	else if(s==3&&e==9||s==9&&e==3)
	{
		if(vis[6]) return true;
		else return false;
	}
	else if(s==4&&e==6||s==6&&e==4)
	{
		if(vis[5]) return true;
		else return false;
	}
	else if(s==7&&e==9||s==9&&e==7)
	{
		if(vis[8]) return true;
		else return false;
	}
	return true;
}

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int cnt=0;
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		sort(a+1,a+1+n);
		int flag=1;
		do
		{
			flag=1;
			memset(vis,0,sizeof(vis));
			vis[a[1]]=1;
			for(int i=2;i<=n;i++)
			{
				if(!judge(a[i-1],a[i])) 
					{flag=0; break;}
				vis[a[i]]=1;
			}
			if(flag)
			{
				for(int i=1;i<=n;i++)
					ans[cnt][i]=a[i];
				cnt++;
			}
				
		}
		while(next_permutation(a+1,a+1+n));
		printf("%d\n",cnt);
		for(int i=0;i<cnt;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(j==n) printf("%d\n",ans[i][j]);
				else printf("%d ",ans[i][j]);
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值