POJ 1077 Eight
题目链接:POJ 1077【Eight】
思路
将X看作9,本题可以视为1-9的全排列所以使用康拓展开作为哈希函数。所以结构体使用pre存储前一个状态的下标,number存储当前状态在结构体数组中的下标,oper存储上一个状态到当前状态的操作,zeroSite记录当前状态下0的位置,state存储当前状态的哈希函数值,num数组存储当前状态下的八码图其中x用9代替。
所以在输入时需要对输入的数据进行特判处理,找出x的位置,并将x用9代替。然后BFS就是一个常规的BFS,中间关于x的移动判断和操作的上下左右需要特殊判断一下,如果移动后出现没出现过的新状态则,将新状态放入结构体数组中并加入队列继续搜索,直到出现一个和结果相同的状态,此时就利用pre,不断回溯查找上一个状态的下标,并存储,最后按顺序输出。
代码
#include <iostream> #include <queue> #include <cstring> using namespace std; #define ll long long const int N = 5e5 + 10; #define target 0 struct eight { int pre; int number; char oper; int zeroSite; int state; int num[10]; } puzzle[N], start; int h[10]={1,1,2,6,24,120,720,5040,40320,362880}; int cnt = 0, dir[5] = {1, -1, 3, -3}; bool vis[N]; // 康拓展开 int cantor(struct eight a) { int res = 0, fac = 1; for (int i = 1; i < 9; i++) { int temp = 0; for (int j = i + 1; j <= 9; j++) { if (a.num[i] > a.num[j]) temp++; } res += temp * h[9 - i]; } return res; } // 判断x是否可以做出dir的移动 bool check(int x, int dir) { if (dir == -1 && (x == 1 || x == 4 || x == 7)) return false; if (dir == 1 && (x == 3 || x == 6 || x == 9)) return false; if (dir == -3 && (x == 1 || x == 2 || x == 3)) return false; if (dir == 3 && (x == 7 || x == 8 || x == 9)) return false; return true; } // 回溯操作,并存储输出 void print(int x) { int store[N], cnt = 0; while (x) { store[++cnt] = x; x = puzzle[x].pre; } for (int i = cnt; i >= 1; i--) { cout << puzzle[store[i]].oper; } cout << endl; } void bfs() { vis[start.state] = true; queue<struct eight> q; q.push(start); int num = 0; while (!q.empty()) { struct eight now = q.front(); q.pop(); if (now.state == target) { print(now.number); return; } for (int i = 0; i < 4; i++) { struct eight dnow = now; if (check(dnow.zeroSite, dir[i])) { swap(dnow.num[dnow.zeroSite], dnow.num[dnow.zeroSite + dir[i]]); dnow.zeroSite += dir[i]; dnow.state = cantor(dnow); if (vis[dnow.state] == true) continue; dnow.pre = now.number; dnow.number = cnt; if (i == 0) { dnow.oper = 'r'; } else if (i == 1) { dnow.oper = 'l'; } else if (i == 2) { dnow.oper = 'd'; } else { dnow.oper = 'u'; } puzzle[cnt++] = dnow; vis[dnow.state] = true; q.push(dnow); } } } cout << "unsolvable" << endl; } int main() { memset(vis, 0, sizeof vis); for (int i = 1; i <= 9; i++) { char s; cin >> s; if (s == 'x') { start.num[i] = 9; start.zeroSite = i; } else { start.num[i] = s - '0'; } } start.pre = -1; start.number = cnt; puzzle[cnt++] = start; start.state = cantor(start); bfs(); return 0; }
合集:
POJ
分类:
ACM / 搜索 / BFS
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)