1. 程式人生 > >八數碼問題

八數碼問題

res node nod 數碼 tar ctime {} prior size

傳送門

//Twenty
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#define INF 0xfffffff
using namespace std;
typedef long long LL;
const int maxn=362880+5;
int T,a[10],b[10],p[10],f[maxn],d[maxn],g[maxn]; 

void read(int &ret) {
    int f=1; ret=0; char ch=getchar();
    while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
    if(ch==‘-‘) f=-1,ch=getchar();
    for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) ret=ret*10+ch-‘0‘; ret*=f;
}

struct node {
	int x;
	node(int x):x(x){}
    friend bool operator <(const node &A,const node &B) {
	    return  d[A.x]+g[A.x]>d[B.x]+g[B.x];
	}
};

priority_queue<node>que;

int get_rk(int *q) {
   int res=0;
   for(int i=1;i<10;i++) {
   	   int tp=0;
       for(int j=i+1;j<10;j++) 
	       if(q[j]<q[i]) tp++; 
	   res+=tp*p[9-i];
   }
   return res+1; 
}

void get_b(int x) {
	int tp[10],vis[10]; x--;
	memset(vis,0,sizeof(vis));
	memset(tp,0,sizeof(tp));
    for(int i=1;i<9;i++) {
	    tp[i]=x/p[9-i];
	    x-=tp[i]*p[9-i];
	}
	for(int i=1;i<10;i++) {
	    int t=tp[i]+1;
	    for(int j=1;j<10;j++) if(!vis[j]&&((--t)==0)) {
		    b[i]=j;
			vis[j]=1;
			break;
		}
	}
	return;
}

void cal(int x){
	if(g[x]!=-1) return;
	g[x]=0;
    for(int i=1;i<10;i++) {
        int tp=b[i];
        int xx=(b[i]-1)/3,yy=b[i]-xx*3;xx++;
        int o=(i-1)/3,p=i-o*3;
        g[x]+=abs(xx-o-1)+abs(yy-p);
	}
	return;
}

void push(int *q,int pr) {
	int x=get_rk(q);
	if(d[pr]+1>=d[x]) return;
	d[x]=min(d[x],d[pr]+1);	
	//if(g[x]!=-1) return;
	cal(x);  
	que.push(node(x));
}

int op(int x,int y) {
    return (x-1)*3+y;
}

void smg(int tpp,int tp,int pr) {
	swap(b[tpp],b[tp]);
	push(b,pr);
	swap(b[tpp],b[tp]);
}

void work() {
	int x=get_rk(a);
	cal(x);  d[x]=0;
	while(!que.empty()) que.pop();
	que.push(node(x));
	int tp;
	while(!que.empty()) {
	    node now=que.top();
	    que.pop();
		if(now.x==1) break; 
		get_b(now.x);
		for(int i=1;i<10;i++) if(b[i]==9) {
		    tp=i; break;
		}
		int xx=(tp-1)/3,yy=tp-xx*3; xx++;
		if(xx>1) {
			int tpp=op(xx-1,yy); 
			smg(tpp,tp,now.x);
		}
		if(xx<3) {
			int tpp=op(xx+1,yy);
			smg(tpp,tp,now.x);
		}
		if(yy>1) {
			int tpp=op(xx,yy-1);
			smg(tpp,tp,now.x);			
		}
		if(yy<3) {
			int tpp=op(xx,yy+1);
			smg(tpp,tp,now.x);
		}
	}
}

void init() {
	read(T);
	p[0]=0; p[1]=1;
	for(int i=2;i<10;i++) p[i]=p[i-1]*i;
	while(T--) {
		memset(g,-1,sizeof(g));
		for(int i=1;i<maxn;i++) d[i]=INF;
	    for(int i=1;i<10;i++) {
		    read(a[i]); 
			if(a[i]==0) a[i]=9;
		}
	    work();
	    if(d[1]!=INF) printf("%d\n",d[1]);
	    else printf("No Solution!\n");
	}
}

int main()
{
	init();
	return 0;
}

  

八數碼問題