用C++来解决3*3拼图

拼图问题

在3*3的拼图中,如何用最少步骤拼好它,这个问题是一个最短路径问题,可以使用BFS来求解,每个节点是一个状态,然后得到最少步骤,中间状态可能需要对每一个状态进行编码或者散列记录才能输出,本代码只解决了求最短步数,其实利用一个栈是可以实现打印解题过程的。

代码

#include<bits/stdc++.h> 
using namespace std;

typedef int State[9];
const int maxstate=1000000;
State st[maxstate],goal;
int dist[maxstate];

const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
int vis[362880],fact[9];

void init_lookup_table(){
    fact[0]=1;
    for(int i=1;i<9;i++)    fact[i]=fact[i-1]*i;
}
int try_to_insert(int s){
    int code=0;
    for(int i=0;i<9;i++){
        int cnt=0;
        for(int j=i+1;j<9;j++)  if(st[s][j]<st[s][i])   cnt++;
        code+=fact[8-i]*cnt;
    }
    if(vis[code])   return 0;
    return vis[code]=1;
}
int bfs(){
    init_lookup_table();
    int front=1,rear=2;
    while(front<rear){
        State& s=st[front];
        if(memcmp(goal,s,sizeof(s))==0) return front;
        int z;
        for(z=0;z<9;z++)    if(!s[z])   break;
        int x=z/3, y=z%3;
        for(int d=0;d<4;d++){
            int newx=x+dx[d];
            int newy=y+dy[d];
            int newz=newx*3+newy;
            if(newx>=0&&newx<3&&newy>=0&&newy<3){
                State& t=st[rear];
                memcpy(&t,&s,sizeof(s));
                t[newz]=s[z];
                t[z]=s[newz];
                dist[rear]=dist[front]+1;
                if(try_to_insert(rear)) rear++;
            }
        }
        front++;
    }
    return 0;
}
int main(){
    freopen("F://inp.txt","r",stdin);
    for(int i=0;i<9;i++)    cin>>st[1][i];
    for(int i=0;i<9;i++)    cin>>goal[i];
    for(int i=0;i<9;i++){if(i&&i%3==0)  cout<<endl;cout<<st[1][i]<<" ";}
    int ans=bfs();
    if(ans>0)   printf("\nNeed %d steps come out!\n",dist[ans]);
    else    printf("\nNo way!\n");
    for(int i=0;i<9;i++){if(i&&i%3==0)  cout<<endl;cout<<goal[i]<<" ";}
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值