P1379 八数码难题

题面:https://www.luogu.org/problem/P1379
本题直接双向bfs,那么双向bfs就是把初始状态和终止状态都放进队列里,然后将二者设定为不同的方向,同时跑bfs,若目的状态和当前状态相同,目的状态无需再次入队,若目的状态和当前状态方向相反,那么直接输出答案,若目标状态没有入队过,那么把目标状态放进队中.
Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<map>
#include<queue>
using namespace std;
int n,g=123804765;
int a[4][4],fx,fy,nx,ny,dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
queue<int> q;
map<int,int> v,ans;
void bfs(){
    if(n==g){
        printf("0");
        return;
    }
    q.push(n);
    q.push(g);
    ans[n]=0;
    ans[g]=1;
    v[g]=2;
    v[n]=1;
    while(!q.empty()){
        long long now,cur=q.front();
        q.pop();
        now=cur;
        for(int i=3;i>=1;i--){
            for(int j=3;j>=1;j--){
                a[i][j]=now%10;
				now/=10;
                if(a[i][j]==0){
					fx=i;
					fy=j;
				}
            }
		}
        for(int i=0;i<4;i++){
            nx=fx+dx[i],ny=fy+dy[i];
            if(nx<1||nx>3||ny<1||ny>3){
				continue;
			}
            swap(a[fx][fy],a[nx][ny]);
            now=0;
            for(int p=1;p<=3;p++){
                for(int j=1;j<=3;j++){
                    now=now*10+a[p][j];
				}
			}
            if(v[now]==v[cur]){
                swap(a[fx][fy],a[nx][ny]);
                continue;
            }
            if(v[now]+v[cur]==3){
                printf("%d",ans[cur]+ans[now]);
                return;
            }
            ans[now]=ans[cur]+1;
            v[now]=v[cur];
            q.push(now);
            swap(a[fx][fy],a[nx][ny]);
        }   
    }
}
int main(){
    scanf("%d",&n);
    bfs();
	return 0;
}
posted @ 2019-10-11 20:14  prestige  阅读(139)  评论(0编辑  收藏  举报