hihoCoder #1054 滑动解锁

#1054 : 滑动解锁

Time Limit:2000ms
Case Time Limit:1000ms
Memory Limit:256MB

Description

滑动解锁是智能手机一项常用的功能。你需要在3x3的点阵上,从任意一个点开始,反复移动到一个尚未经过的"相邻"的点。这些划过的点所组成的有向折线,如果与预设的折线在图案、方向上都一致,那么手机将解锁。两个点相邻当且仅当以这两个点为端点的线段上不存在尚未经过的点。此外,这条折线还需要至少经过4个点。

为了描述方便,我们给这9个点从上到下、从左到右依次编号1-9。那么1->2->3是不合法的,因为长度不足。1->3->2->4也是合不法的,因为1->3穿过了尚未经过的点2。2->4->1->3->6是合法的,因为1->3时点2已经被划过了。

作为一个爱逛知乎的好少年,小Hi已经知道一共有389112种不同的解锁方案。不过小Hi不满足于此,他希望知道,当已经瞥视到一部分折线的情况下,有多少种不同的方案。

遗憾的是,小Hi看到的部分折线既不一定是连续的,也不知道方向。例如看到1-2-3和4-5-6,那么1->2->3->4->5->6,1->2->3->6->5->4, 3->2->1->6->5->4->8->9等都是合法的方案。

Input

第一行包含一个整数T(1 <= T <= 10),代表测试数据组数。

每个测试数据第一行是一个整数N(0 <= N <= 8),代表小Hi看到的折线段数目。

以下N行每行包含两个整数X, Y (1 <= X, Y <= 9),代表小Hi看到点X和点Y是直接相连的。

Output

对于每组数据输出合法的方案数目。

Sample Input
3  

0  

8  

1 2  

2 3  

3 4  

4 5  

5 6  

6 7  

7 8  

8 9  

4  

2 4  

2 5   

8 5  

8 6  
Sample Output
389112  

2  

258

解题:爆搜
 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <cmath>

 5 #include <algorithm>

 6 #include <climits>

 7 #include <vector>

 8 #include <queue>

 9 #include <cstdlib>

10 #include <string>

11 #include <set>

12 #include <stack>

13 #define LL long long

14 #define pii pair<int,int>

15 #define INF 0x3f3f3f3f

16 using namespace std;

17 const int maxn = 600000;

18 bool mp[maxn][10][10] = {false},vis[10] = {false};

19 set<int>s;

20 int tot = 0,ans[10];

21 vector<int>g[10][10];

22 void init() {

23     g[1][3].push_back(2);

24     g[3][1].push_back(2);

25     g[4][6].push_back(5);

26     g[6][4].push_back(5);

27     g[7][9].push_back(8);

28     g[9][7].push_back(8);

29     g[1][7].push_back(4);

30     g[7][1].push_back(4);

31     g[2][8].push_back(5);

32     g[8][2].push_back(5);

33     g[3][9].push_back(6);

34     g[9][3].push_back(6);

35     g[1][9].push_back(5);

36     g[9][1].push_back(5);

37     g[3][7].push_back(5);

38     g[7][3].push_back(5);

39 }

40 void dfs(int num,int cur,int dep) {

41     if(cur > 3){

42         int sum = 0;

43         for(int i = 0; i < cur; ++i)

44             sum = sum*10 + ans[i];

45         if(!s.count(sum)){

46             s.insert(sum);

47             for(int i = 1; i < cur; ++i){

48                 mp[tot][ans[i-1]][ans[i]] = true;

49                 mp[tot][ans[i]][ans[i-1]] = true;

50             }

51 

52             tot++;

53         }

54     }

55     if(cur >= dep) return;

56     for(int i = 1; i <= 9; ++i) {

57         if(vis[i]) continue;

58         vis[i] = true;

59         bool flag = true;

60         ans[cur] = i;

61         for(int j = g[num][i].size()-1; j >= 0; --j){

62             if(!vis[g[num][i][j]]) {

63                 flag = false;

64                 break;

65             }

66         }

67         if(flag) dfs(i,cur+1,dep);

68         vis[i] = false;

69     }

70 }

71 int main() {

72     init();

73     dfs(0,0,9);

74     int n,m,x[10],y[10];

75     scanf("%d",&n);

76     while(n--){

77         scanf("%d",&m);

78         for(int i = 0; i < m; ++i)

79             scanf("%d %d",x+i,y+i);

80         int ans = 0;

81         for(int i = 0; i < tot; ++i){

82             int j;

83             for(j = 0; j < m; ++j)

84                 if(!mp[i][x[j]][y[j]]) break;

85             if(j == m) ans++;

86         }

87         printf("%d\n",ans);

88     }

89     return 0;

90 }
View Code

 

你可能感兴趣的:(code)