算法竞赛入门经典——八数码 (Cantor展开 + 一堆c++语法)

Experience:

1.如果本地ac而oj上re,很有可能是数组开小了

2.

typedef int State[9];//相当于一种结构体,在st中作为数组的第二维

3.Cantor板子

int code = 0;
for (int i = 0; i < 9; i++) {
  int cnt = 0;
  for (int j = i + 1; j < 9; j++) if (a[j] < a[i]) cnt++;
  code += fact[8 - i] * cnt;
}

4.返回值与0的大小关系即为str1与str2的大小关系

memcmp(goal, s, sizeof(s))

5.取地址可以访问二维数组中的某一维,从而简化代码

State &a = st[s];

6.memcpy 目标/源头/要被复制的字节数

memcpy(&t, &s, sizeof(s));

7.手写队列BFS的一种写法

int bfs() {
  //do something 
  int l = 1, r = 2;
  while (l < r) {
    ...;//取出队首
    if (ok) return l;
    for(...) {
   st[r] = ... ....
if (ok) r++; } l++; } return 0; }

 

Code:

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 typedef int State[9];//相当于一种结构体,在st中作为数组的第二维
 5 const int maxstate = 1e6 + 10;
 6 State st[maxstate], goal = {1, 2, 3, 4, 5, 6, 7, 8, 0};
 7 int dist[maxstate];
 8 
 9 int vis[362880], fact[9];
10 void init_lookup_table() {
11   fact[0] = 1;
12   for (int i = 1; i < 9; i++) fact[i] = fact[i - 1] * i;
13 }
14 int try_to_insert(int s) {
15   State &a = st[s]; //取地址<->别名
16   //Cantor板子
17   int code = 0;
18   for (int i = 0; i < 9; i++) {
19     int cnt = 0;
20     for (int j = i + 1; j < 9; j++) if (a[j] < a[i]) cnt++;
21     code += fact[8 - i] * cnt;
22   }
23   if (vis[code]) return 0;
24   return vis[code] = 1;
25 }
26 
27 const int dx[] = {-1, 1, 0, 0};
28 const int dy[] = {0, 0, -1, 1};
29 int bfs() {
30   init_lookup_table();
31   int l = 1, r = 2;
32   while (l < r) {
33     State &s = st[l];//取出队首
34     if (memcmp(goal, s, sizeof(s)) == 0) return l;
35     int z;
36     for (z = 0; z < 9; z++) if (!s[z]) break;
37     int x = z / 3, y = z % 3;
38     for (int i = 0; i < 4; i++) {
39       int tx = x + dx[i], ty = y + dy[i], tz = tx * 3 + ty;
40       if (tx >= 0 && ty >= 0 && tx < 3 && ty < 3) {
41         State &t = st[r];
42         memcpy(&t, &s, sizeof(s));
43         t[tz] = s[z];
44         t[z] = s[tz];
45         dist[r] = dist[l] + 1;
46         if (try_to_insert(r)) r++;
47       }      
48     }
49     l++;
50   }
51   return 0;
52 }
53 
54 int main() {
55   for (int i = 0; i < 9; i++) {
56     char c[2];
57     scanf("%s", c);
58     st[1][i] = isdigit(c[0]) ? c[0] - '0' : 0;
59   }
60   //for (int i = 0; i < 9; i++) printf("%d ", st[1][i]); puts("");
61   int ans = bfs();
62   if (ans > 0) printf("%d", dist[ans]);
63   else printf("-1");
64   return 0;
65 }

 

 
posted @ 2021-09-12 20:40  _vv123  阅读(92)  评论(0编辑  收藏  举报