HDU 1043 Eight(经典八数码问题)对比POJ 1077(bfs)

题目链接:点击打开链接


事情是这样的,我先在TLE无数发之后A了POJ的1077,然后在VJ上看到“原题”,然而,此原题被我TLE5发MLE9发,最后从学长那里学得记录路径的方法之后才过,却原来,这道所谓原题并非原题!!!HDU 的1043和POJ的1077都叫Eight,但是由于HDU上是多组数据POJ上单组,所以POJ上直接正常bfs搜索, HDU上则需要预处理。。。

方法是一样的,对于输入的串,保存成数组,其中x的位置用0代替,最终目标就是123456780

o对了,哈希用的康拓展开,所以12356780对应的康拓展开值是46234

然后正常bfs搜索就好,不过由于时间卡的很死,对于POJ的1077据说双向bfs会更快

然后,HDU的内存不愿多说,MLE之后换了个记录路径的方法

具体见代码:

poj 1077:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cmath>
#include<stdlib.h>
#include<cctype>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int ans = 46234;//123456780
int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int ct (int s[])
{
    int sun = 0, tmp;
    for (int i = 0; i < 9; i++)
    {
        tmp = 0;
        for (int j = i + 1; j < 9; j++)
            if (s[j] < s[i]) tmp++;
        sun += (tmp * fac[9 - i - 1]);
    }
    return sun + 1;
}
bool vis[400000];
struct Node
{
    int g[10];
    int x;
    int st;
    string p;
} h;
const int dx[] = { -1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};
char dd[] = {'u', 'd', 'l', 'r'};
string path;
void bfs()
{
    queue<Node>q;mem(vis,0);
    q.push (h);
//    vis[h.st] = 1;
    while (!q.empty() )
    {
        h = q.front();
        q.pop();
        if (h.st == ans)
        {
            path = h.p;
            return;
        }
        int x = h.x / 3;
        int y = h.x % 3;
        for (int i = 0; i < 4; ++i)
        {

            int xx = x + dx[i];
            int yy = y + dy[i];
            if (xx >= 0 && yy >= 0 && xx < 3 && yy < 3)
            {
                Node nx = h;
                nx.x = xx * 3 + yy;
                swap (nx.g[h.x], nx.g[nx.x]);
                nx.st = ct (nx.g);
                if (!vis[nx.st])
                {
                    if (nx.st == ans)
                    {
                        path = nx.p + dd[i];
                        return;
                    }
                    vis[nx.st] = 1;
                    nx.p += dd[i];
                    q.push (nx);
                }
            }
        }
    }
}
int main()
{
    char tmp;
    while (~scanf("%c",&tmp))
    {
        if (tmp == 'x')
        {
            h.g[0] = 0;
            h.x = 0;
        }
        else h.g[0] = tmp-48;
        for (int i = 1; i < 9; ++i)
        {
            scanf(" %c",&tmp);
            if (tmp == 'x')
            {
                h.g[i] = 0;
                h.x = i;
            }
            else h.g[i] = tmp - 48;
        }
        getchar();
        h.st = ct (h.g);
        h.p.clear();
        path = "unsolvable";
        bfs();
        cout<<path<<endl;
    }
    return 0;
}

HDU 1043:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cmath>
#include<stdlib.h>
#include<cctype>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,-1,1};//上下左右
const char dd[] = "durl";
const int ans = 46234;//123456780
int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int ct (int s[])
{
    int sun = 0, tmp;
    for (int i = 0; i < 9; i++)
    {
        tmp = 0;
        for (int j = i + 1; j < 9; j++)
            if (s[j] < s[i]) tmp++;
        sun += (tmp * fac[9 - i - 1]);
    }
    return sun + 1;
}
struct Node
{
    int g[10];
    int x;
    int st;
}h;
struct No
{
    int fa;
    char mo;
}moo[400000];
bool vis[400000];
void bfs()
{
    queue<Node>q;
    q.push(h);
    vis[h.st] = 1;
    while (!q.empty())
    {
        h = q.front();q.pop();
        int x = h.x / 3;
        int y = h.x % 3;
        for (int i = 0; i < 4; ++i)
        {
            int xx = x + dx[i];
            int yy = y + dy[i];
            if (xx >= 0 && yy >= 0 && xx < 3 && yy < 3)
            {
                Node nx = h;
                nx.x = xx * 3 + yy;
                swap (nx.g[h.x], nx.g[nx.x]);
                nx.st = ct (nx.g);
                if (!vis[nx.st])
                {
                    vis[nx.st] = 1;
                    moo[nx.st].mo = dd[i];
                    moo[nx.st].fa = h.st;
                    q.push (nx);
                }
            }
        }
    }
}
void init()
{
    for (int i = 0;i < 8;++i) h.g[i] = i+1;
    h.g[8] = 0;
    h.x = 8;
    h.st = ans;
    moo[ans].fa = -1;
    bfs();
}
int main()
{
    char tmp;init();int s[10];
    while (cin>>tmp)
    {
        if (tmp == 'x') s[0] = 0;
        else s[0] = tmp - 48;
        for (int i = 1;i < 9;++i)
        {
            cin>>tmp;
            if(tmp == 'x') s[i] = 0;
            else s[i] = tmp - 48;
        }
        int st = ct (s);
        if (st == ans)
        {
            puts("");
            continue;
        }
        if (!vis[st]) printf("unsolvable\n");
        else
        {
            while (moo[st].fa!=-1)
            {
                printf("%c",moo[st].mo);
                st = moo[st].fa;
            }
            puts("");
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值