您的位置:首页 > 其它

Codevs1225 八数码难题

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

思路:使用IDA*算法。估价函数为现在棋盘与目标棋盘的对应元素不同的个数。剪枝:若当前深度加上估价函数值大于限定的深度则剪枝。搜索时,每次拿出估价函数最小的节点进行扩展,这一操作利用优先队列支持。整体上属于广搜。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int tar[5][5]={
                        {0,0,0,0,0},
                        {0,1,2,3,0},
                        {0,8,0,4,0},
                        {0,7,6,5,0},
                        {0,0,0,0,0}
                    };
const int dx[5]={0,-1,1,0,0};
const int dy[5]={0,0,0,1,-1};
const int mod=100007;
struct node
{
    int x,y,eva,id,map[5][5];
    bool operator <(const node &a) const
    {
        return eva>a.eva;
    }
};
int map[5][5],ans=10000,maxdep,x,y;
bool flag=0;

void init()
{
    char ch[10];
    scanf("%s",ch);
    int i,k=0,j=1;
    for (i=0;i<=8;++i)  /*先转化为矩阵形式*/
    {
        k++;
        if (k>3)
        {
            k%=3;
            j++;
        }
        map[j][k]=ch[i]-'0';
        if (ch[i]=='0')
        {
            x=j;
            y=k;
        }
    }
}

node addnode(int x,int y,int eva,int id,int map[5][5])
{
    node tmp;
    tmp.x=x;
    tmp.y=y;
    tmp.eva=eva;
    tmp.id=id;
    memcpy(tmp.map,map,sizeof(tmp.map));
    return tmp;
}

int evaluate(int map[5][5])
{
    int res=0;
    for (int i=1;i<=3;++i)
      for (int j=1;j<=3;++j)
        if (map[i][j]!=tar[i][j])
          res++;
    return res;
}

priority_queue<node> q;

void idastar()
{
    int i,j,k,tmp=evaluate(map);
    while (!q.empty())
      q.pop();
    q.push(addnode(x,y,tmp,0,map));
    while (!q.empty())
    {
        node best=q.top();
        q.pop();
        if (best.eva==0)
        {
            flag=1;
            break;
        }
        int x=best.x,y=best.y;
        int nowmap[5][5];
        memcpy(nowmap,best.map,sizeof(nowmap));
        for (i=1;i<=4;++i)
        {
            int xx=x+dx[i];
            int yy=y+dy[i];
            if (xx<1 || xx>3 || yy<1 || yy>3)
               continue;
            swap(nowmap[x][y],nowmap[xx][yy]);
            int noweva=evaluate(nowmap);
            if (noweva+best.id<ans && noweva+best.id<=maxdep)
            {
                q.push(addnode(xx,yy,noweva,best.id+1,nowmap));
            }
            swap(nowmap[x][y],nowmap[xx][yy]);
        }
    }
}

int main()
{
    init();
    for (maxdep=0;maxdep<=100;++maxdep)  /*限定深度*/
    {
        idastar();
        if (flag)
        {
            printf("%d",maxdep);
            break;
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: