hihoCoder#1054 滑动解锁

原题地址

 

回溯搜索

对于每个待枚举的点,检查:

1. 度数检查:是否违反了出度入度限制。因为生成的路径除了首尾节点外,其他节点的出度和入度只能为2

2. 共线检查:是否违反了共线条件。即跨越了尚未枚举过的节点

对于枚举产生的路径,检查:

1. 长度检查:长度是否大于等于4

2. 完整性检查:是否包含了片段中出现的所有边

 

代码:

  1 #include <iostream>
  2 #include <cstring>
  3 
  4 using namespace std;
  5 
  6 int impossible[100];
  7 
  8 bool integrity_check(int piece[9][9], int path[9][9]) {
  9   for (int i = 0; i < 9; i++)
 10     for (int j = 0; j < 9; j++)
 11         if (piece[i][j] && !path[i][j])
 12           return false;
 13   return true;
 14 }
 15 
 16 bool degree_check(int piece[9][9], int path[9][9], int b, int e) {
 17   if (piece[b][e])
 18     return true;
 19 
 20   int bdegree = 0;
 21   int edegree = 0;
 22 
 23   for (int i = 0; i < 9; i++) {
 24     bdegree += path[b][i] || piece[b][i] ? 1 : 0;
 25     edegree += path[e][i] || piece[e][i] ? 1 : 0;
 26   }
 27 
 28   return bdegree < 2 && edegree < 2;
 29 }
 30 
 31 bool collineation_check(int visited[9], int b, int e) {
 32   int t = (b + 1) * 10 + e + 1;
 33   return impossible[t] < 0 || visited[impossible[t] - 1];
 34 }
 35 
 36 bool check(int piece[9][9], int path[9][9], int visited[9], int b, int e) {
 37   if (visited[e])
 38     return false;
 39 
 40   return degree_check(piece, path, b, e) && collineation_check(visited, b, e);
 41 }
 42 
 43 int search(int piece[9][9], int path[9][9], int visited[9], int p, int len) {
 44   int res = 0;
 45 
 46   if (len >= 4 && integrity_check(piece, path))
 47     res++;
 48 
 49   for (int i = 0; i < 9 && len < 9; i++) {
 50     if (check(piece, path, visited, p, i)) {
 51       visited[i] = 1;
 52       path[p][i] = path[i][p] = 1;
 53       res += search(piece, path, visited, i, len + 1);
 54       path[p][i] = path[i][p] = 0;
 55       visited[i] = 0;
 56     }
 57   }
 58 
 59   return res;
 60 }
 61 
 62 int main() {
 63   int T;
 64   memset(impossible, -1, sizeof(int) * 100);
 65   impossible[13] = 2;
 66   impossible[46] = 5;
 67   impossible[79] = 8;
 68   impossible[17]= 4;
 69   impossible[28]= 5;
 70   impossible[39]= 6;
 71   impossible[19]= 5;
 72   impossible[37]= 5;
 73   impossible[31]= 2;
 74   impossible[64]= 5;
 75   impossible[97]= 8;
 76   impossible[71]= 4;
 77   impossible[82]= 5;
 78   impossible[93]= 6;
 79   impossible[91]= 5;
 80   impossible[73]= 5;
 81 
 82   cin >> T;
 83   while (T--) {
 84     int N;
 85     int piece[9][9] = {{0, 0}};
 86     int path[9][9] = {{0, 0}};
 87     int visited[9] = {0};
 88     int res = 0;
 89 
 90     cin >> N;
 91     for (int i = 0; i < N; i++) {
 92       int a, b;
 93       cin >> a >> b;
 94       piece[a - 1][b - 1] = piece[b - 1][a - 1] = 1;
 95     }
 96 
 97     for (int i = 0; i < 9; i++) {
 98       visited[i] = 1;
 99       res += search(piece, path, visited, i, 1);
100       visited[i] = 0;
101     }
102 
103     cout << res << endl;
104   }
105   return 0;
106 }

 

转载于:https://www.cnblogs.com/boring09/p/4375554.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值