UVa 10422 - Knights in FEN

来源:互联网 发布:三国杀手游源码 编辑:程序博客网 时间:2024/04/28 04:31

传送门UVa 10422 - Knights in FEN


这题和八数码问题是一样的,但是我还是不会写。。。

参考了shuangde800的解题报告。

说是参考,其实就是看一句理解一句写一句。。。对哈希表和八数码有了一个初步的了解。

还有这篇文章各种常用字符串Hash函数比较,很厉害的样子。。

因为以前都是用结构体+指针方式写链表,突然看到数组表示的,很不习惯。

在这里理解了很久。

inline int TryToInsert(int s){    int h = BKDRHash(que[s]);    int u = head[h];    while (u)    {        if (memcmp(que[u], que[s], sizeof(que[s])) == 0)            return 0;        u = next[u];    }    next[s] = head[h];  //把当前的哈希值的首部放到后面    head[h] = s;    //放到对应的哈希值的首部    return 1;}


其实实际上就是这么一个图




如果没有冲突的哈希值,一切好说。

如果有冲突的,就顺着链表找下去,如果找不到,说明这个状态没有到达过,把它插入到哈希值的第一位,连接原本的第一位和现在的第一位。


#include <cstdio>#include <cstring>using namespace std;const int MAXN = 5000000;const int HashSize = 3000000;typedef char State[5][5];State que[MAXN], start, goal = {{'1','1','1','1','1'},                                {'0','1','1','1','1'},                                {'0','0',' ','1','1'},                                {'0','0','0','0','1'},                                {'0','0','0','0','0'}};int dir[][2] = {{-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}};int step[MAXN], ans;int head[HashSize], next[MAXN];inline int BKDRHash(State &s);inline int TryToInsert(int s);void BFS();int main(){    //freopen("input.txt", "r", stdin);    int i, j, T;    scanf("%d%*c", &T);    while (T--)    {        for (i = 0; i < 5; i++)            gets(start[i]);        BFS();        if (ans != -1)            printf("Solvable in %d move(s).\n", ans);        else            printf("Unsolvable in less than 11 move(s).\n");    }    return 0;}inline int BKDRHash(State &s){    unsigned int seed = 131;    unsigned int hashValue = 0;    for (int i = 0; i < 5; i++)        for (int j = 0; j < 5; j++)            hashValue = hashValue * seed + s[i][j];    return (hashValue & 0x7FFFFFF) % HashSize;}inline int TryToInsert(int s){    int h = BKDRHash(que[s]);    int u = head[h];    while (u)    {        if (memcmp(que[u], que[s], sizeof(que[s])) == 0)            return 0;        u = next[u];    }    next[s] = head[h];  //把当前的哈希值的首部放到后面    head[h] = s;    //放到对应的哈希值的首部    return 1;}void BFS(){    memset(head, 0, sizeof(head)); //Initial the hash table    int front = 0, rear = 1;    memcpy(que[0], start, sizeof(start));    step[0] = 0;    while (front < rear)    {        State &s = que[front];        if (step[front] > 10)        {            ans = -1;            return;        }        if (memcmp(goal, s, sizeof(s)) == 0)        {            ans = step[front];            return;        }        int x, y;        bool flag = false;        for (int i = 0; i < 5; i++)            for (int j = 0; j < 5; j++)            {                if (flag)                    break;                if (s[i][j] == ' ')                {                    x = i, y = j;                    flag = true;                    break;                }            }        for (int i = 0; i < 8; i++)        {            int dx = x + dir[i][0];            int dy = y + dir[i][1];            if (dx >= 0 && dx < 5 && dy >= 0 && dy < 5)            {                State &t = que[rear];                memcpy(t, s, sizeof(s));                t[dx][dy] = s[x][y];                t[x][y] = s[dx][dy];    //移动空格                step[rear] = step[front] + 1;                if (TryToInsert(rear))  //如果不存在重复的,就放到队列里。                    rear++;            }        }        front++;    }    ans = -1;}


0 0
原创粉丝点击