八数码问题(HDU 1043)

#include<iostream>
#include<queue>
#include<stack>
#include<memory.h>
#include<math.h>
#include<algorithm>

#define INF 400000
#define END 322560

using namespace std;

struct NODE
{
    int board[3][3];
    int x,y;
    int h,g;
    int state;

    bool operator < (const NODE & node) const
    {
        return h != node.h ? h > node.h : g > node.g;
    }
}sta;

int dir1[4][2] = {{0,-1},{0,1},{-1,0},{1,0}};
char dir2[4] = {'l','r','u','d'};
int fact[9] = {1,1,2,6,24,120,720,5040,40320};
int vis[INF],pre[INF];

void init(char *);
int get_hash(const NODE &);
void aStar();
void print();
int check(const NODE &);
int val(const NODE &);

int main()
{
    char str[100];

   // freopen("Sample Input.txt","r",stdin);

    while(cin.getline(str,100))
    {
        init(str);

        if(!check(sta))
        {
            cout << "unsolvable" << endl;
        }
        else
        {
            aStar();
            print();
        }
    }

    return 0;
}

void init(char str[])
{
    int pos = 0;
    for(int i = 0;i < 3;i++)
    {
        for(int j = 0;j < 3;j++)
        {
            int pos = (3 * i + j) * 2;

            if(str[pos] == 'x')
            {
                sta.board[i][j] = 0;
                sta.x = i;
                sta.y = j;
            }
            else
            {
                sta.board[i][j] = str[pos] - '0';
            }
        }
    }

    sta.g = 0;
    sta.h = val(sta);
    sta.state = get_hash(sta);
    memset(vis,-1,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    vis[sta.state] = 1;
}

int get_hash(const NODE & node)                                        //用康托展开获得此时排列在所有排列中的位置
{
    int num[9];

    for(int i = 0;i < 3;i++)
    {
        for(int j = 0;j < 3;j++)
        {
            num[3 * i + j] = node.board[i][j];
        }
    }

    int res = 0;
    for(int i = 0;i < 9;i++)
    {
        int cnt = 0;
        for(int j = 0;j < i;j++)
        {
            if(num[j] > num[i])
            {
                cnt++;
            }
        }
        res += cnt * fact[i];
    }

    return res;
}

void aStar()
{
    priority_queue<NODE> que;
    que.push(sta);

    while(!que.empty())
    {
        NODE cur = que.top();
        que.pop();

        if(cur.state == END)
        {
            return;
        }

        for(int i = 0;i < 4;i++)
        {
            NODE next = cur;

            next.x += dir1[i][0];
            next.y += dir1[i][1];

            if(next.x < 0 || next.y < 0 || next.x > 2 || next.y > 2)
            {
                continue;
            }

            swap(next.board[cur.x][cur.y],next.board[next.x][next.y]);

            next.state = get_hash(next);

            if(vis[next.state] < 0 && check(next))
            {
                vis[next.state] = i;
                pre[next.state] = cur.state;
                next.g++;
                next.h = val(next);
                que.push(next);
            }
        }
    }
}

void print()
{
    int pos = END;
    stack<char> path;

    while(pre[pos] != -1)
    {
        path.push(dir2[vis[pos]]);
        pos = pre[pos];
    }

    while(!path.empty())
    {
        cout << path.top();
        path.pop();
    }
    cout << endl;
}

int check(const NODE & node)
{
    int num[9];

    for(int i = 0;i < 3;i++)
    {
        for(int j = 0;j < 3;j++)
        {
            num[3 * i + j] = node.board[i][j];
        }
    }

    int cnt = 0;
    for(int i = 0;i < 9;i++)
    {
        if(num[i] == 0)
        {
            continue;
        }
        for(int j = 0;j < i;j++)
        {
            if(num[j] != 0 && num[j] > num[i])
            {
                cnt++;
            }
        }
    }

    if(cnt % 2 == 0)
        return 1;
    else
        return 0;
}


int val(const NODE & node)
{
    int sum = 0;

    for(int i = 0;i < 3;i++)
    {
        for(int j = 0;j < 3;j++)
        {
            if(node.board[i][j])
            {
                sum += abs((node.board[i][j] - 1) / 3 - i) + abs((node.board[i][j] - 1) % 3 - j);
            }
        }
    }

    return sum;

}



不知道为什么把priority_queue改成queue结果就不一样了,求解。。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值