codevs 1225_八数码难题_bfs+hash

来源:互联网 发布:拼音在线发音软件 编辑:程序博客网 时间:2024/05/16 12:32

题目描述

Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。


思路

显然一共有9!种情况,而且这个数不是很大

所以我们可以直接打一个单向bfs

将每一种状态都看成是一个字符串,那么我们在找到’0’的位置后按常理来说可以往”上,下,左,右”四个方向进行交换,那么很容易看出如果将这个3*3的矩形转换为了一个字符串后,这四个方向分别对应的变换位置就是{-3,3,-1,1},那么这样的话就可以很容易的用字符串表示当前的状态并进行转化

打广搜的话,很明显要记忆化,不然那么多种状态,那么多重复,不爆队列就怪了

用了map进行判重(毕竟好写)
然而map会超时,所以改用hash


#include <stdio.h>#include <string>#include <cstring>#include <map>#include <iostream>#include <queue>#include <cstdlib>using namespace std;#define p 10000007string start, ed="123804765";int h[p+1];int dx[5]={0,1,-1,3,-3};int fl=0;int insert(int x){    int i=x%p;    while (h[i]!=0) i=(i+1)%p;    h[i]=x;}int find(int x){    int i=x%p;    while (h[i]!=0&&h[i]!=x) i=(i+1)%p;    if (h[i]==x) return 1;    return 0;}int bfs(){    queue<string> t;    queue<int> state;    t.push(start);    state.push(0);    int xx=std::atoi(start.c_str());    insert(xx);    while (!t.empty())    {        string now = t.front();        int ns = state.front();        t.pop(); state.pop();        int l = now.find('0');        for (int i = 1; i <= 4; i++)        {            if (l + dx[i] < 0 || l + dx[i] > 8) continue;            if ((l == 3 && dx[i] == -1)||(l == 6 && dx[i] == -1)) continue;            if ((l == 2 && dx[i] == 1)||(l == 5 && dx[i] == 1)) continue;            string ne = now, ch = now.substr(l + dx[i], 1);            ne.replace(l, 1, ch);            ch = '0';            ne.replace(l+dx[i], 1, ch);            int xx=std::atoi(ne.c_str());            if (!find(xx))             {                insert(xx);                t.push(ne);                state.push(ns + 1);                if (ne == ed)                {                    fl = 1;                    printf("%d\n", ns + 1);                    return 0;                }            }        }    }}int main(){    for (int i = 1; i <= 9; i++)    {        char ch = getchar();        while (ch < '0' || ch > '8') {ch = getchar();}        start += ch;    }    bfs();    if (fl == 0) printf("-1");}
原创粉丝点击