题目描述
思路
bfs主要问题就是走重复路的问题,需要设置一个vis数组防止走重复路,怎么把一个二维数组表示成一个数,扩展来说就是怎么把状态表示成一个数,看了别人的代码,可以二进制的数来记录状态,4x4的数组状态不会超过2^(17)。
然后就是怎么走的问题,规定只能向下,下右走,而向上,向左就是向下,向右的逆运算。if筛选能够向下,向右走的点就可以了。
代码
#include <cstdio> #include <cstring> #include <queue> char st[5][5], ed[5][5]; int js[5][5], num_ed, tmp, cur, v, vis[135000]; std::queue<int> q; void init() { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { js[i][j] = 1 << (i * 4 + j); } } } int get(char arr[][5]) { int res = 0; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { res += js[i][j] * (arr[i][j] - '0'); } } return res; } void trans(int x, char arr[][5]) { for (int i = 3; i >= 0; --i) { for (int j = 3; j >= 0; --j) { arr[i][j] = x / js[i][j] + '0'; x %= js[i][j]; } } } void swap(char &x, char &y) { char t = x; x = y; y = t; } int main() { for (int i = 0; i < 4; ++i) scanf("%s", st[i]); for (int i = 0; i < 4; ++i) scanf("%s", ed[i]); init(); num_ed = get(ed); tmp = get(st); q.push(tmp); memset(vis, 0x3f, sizeof(vis)); vis[tmp] = 0; while (!q.empty()) { cur = q.front(); v = vis[cur]; q.pop(); if (cur == num_ed) break; trans(cur, st); for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { if (i < 3) { swap(st[i][j], st[i + 1][j]); tmp = get(st); if (vis[tmp] > v + 1) { q.push(tmp); vis[tmp] = v + 1; } swap(st[i + 1][j], st[i][j]); } if (j < 3) { swap(st[i][j], st[i][j + 1]); tmp = get(st); if (vis[tmp] > v + 1) { q.push(tmp); vis[tmp] = v + 1; } swap(st[i][j], st[i][j + 1]); } } } } printf("%d", vis[num_ed]); return 0; }