码迷,mamicode.com
首页 > 其他好文 > 详细

luogu#P1379 八数码难题

时间:2019-10-29 21:32:31      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:wap   main   switch   namespace   break   题意   amp   ons   case   

题意:

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

解法:

A*

#include<iostream>
#include<queue>
#include<map>
#define END 123804765

using namespace std;
struct node
{
    int now,step,g;
    bool operator < (const node &x)const 
    {
        return x.g<g;   
    }
};

int end[9]={1,2,3,8,0,4,7,6,5};
int a[9];
priority_queue<node> q;
node tmp;

map<int,int> m;


inline int fnd(int x);
inline int abs(int x);
void in();
void move(int i,int t);
void out(int x);
int g(int now,int step);
int main()
{
    int s;

    cin>>s; 
    tmp.now=s; tmp.step=0; tmp.g=0; 
    q.push(tmp);
    
    while(1)
    {
        int x;
        tmp=q.top(); q.pop();
        
        if(m.count(tmp.now))
            continue;
        m[tmp.now]=1;
        
    
        if(tmp.now==END)
        {
            cout<<tmp.step;
            return 0;
        }
        out(tmp.now);
        
        
        for(int i=0;i<9;i++)
            if(!a[i])
            {
                x=i;
                break;
            }
        
        
        if((x+1)%3) //right
            move(x,1);
        if(x%3) //left
            move(x,-1);
        if(x>=0&&x<=5) //up
            move(x,3);
        if(x>=3&&x<=8) //down
            move(x,-3); 
    
    }   
    return 0;
}
int g(int x,int step)
{
    int ans=step*2;
    for(int i=0;i<9;i++)
        ans+=abs(fnd(a[i])-i);
    return ans;
}
void out(int x)
{
    for(int i=8;i>=0;i--)
    {
        a[i]=x%10;
        x/=10;
    }
}
void move(int i,int t)
{
    if(i+t<=8&&i+t>=0)
    {
        swap(a[i],a[i+t]);
        in();
        swap(a[i],a[i+t]);
    }
}
void in()
{
    int ans=0;
    for(int i=0;i<9;i++)
        ans=ans*10+a[i];
    node z;
    z.step=tmp.step+1; z.now=ans;
    z.g=g(ans,z.step);
    //m[ans]=1;
    q.push(z);
}
inline int abs(int x)
{
    return x>0?x:-1;
}
inline int fnd(int x)
{
    switch(x)
    {
        case 1 : return 0;
        case 2 : return 1;
        case 3 : return 2;
        case 4 : return 5;
        case 5 : return 8;
        case 6 : return 7;
        case 7 : return 6;
        case 8 : return 3;
        case 0 : return 4;
    }
}

luogu#P1379 八数码难题

标签:wap   main   switch   namespace   break   题意   amp   ons   case   

原文地址:https://www.cnblogs.com/nenT/p/11761319.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!