描述The 15-puzzle has been around for over 100 years; even if you don’t know it by that name, you’ve seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let’s call the missing tile ‘x’; the object of the puzzle is to arrange the tiles so that they are ordered as:

 1  2  3  4 
 5  6  7  8 
 9 10 11 12 
13 14 15  x

where the only legal operation is to exchange ‘x’ with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:

 1  2  3  4    1  2  3  4    1  2  3  4    1  2  3  4 
 5  6  7  8    5  6  7  8    5  6  7  8    5  6  7  8 
 9  x 10 12    9 10  x 12    9 10 11 12    9 10 11 12 
13 14 11 15   13 14 11 15   13 14  x 15   13 14 15  x 
           r->           d->           r->

The letters in the previous row indicate which neighbor of the ‘x’ tile is swapped with the ‘x’ tile at each step; legal values are ‘r’,’l’,’u’ and ‘d’, for right, left, up, and down, respectively.

Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing ‘x’ tile, of course).

In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three
arrangement.
输入You will receive a description of a configuration of the 8 puzzle. The description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus ‘x’. For example, this puzzle

 1  2  3 
 x  4  6 
 7  5  8

is described by this list:

 1 2 3 x 4 6 7 5 8

输出You will print to standard output either the word “unsolvable”, if the puzzle has no solution, or a string consisting entirely of the letters ‘r’, ‘l’, ‘u’ and ‘d’ that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line.样例输入

 2  3  4  1  5  x  7  6  8

样例输出

ullddrurdllurdruldr

题解:这题我写了一份代码,输出的步数相同但是答案不同,不知道是哪里的问题,也不知道是不是评测数据只有一种顺序。

    • f(state)=当前状态所有数字与目标的曼哈顿距离之和。
    • 初态与终态逆序队奇偶性相同则可达。
    • 我用的map当作hash,但用康托展开更优。
    • 存下别人的AC代码:
    • #include<bits/stdc++.h>//懒得再debug了...随便找个代码交了 
      using namespace std;
      int a[10],f[4][4],vis[1000010],pre[1000010],path[1000010];
      const int dr[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
      char op[4]={'u','d','l','r'};
      char c[10];
      struct node{
      	int st,d,g,pos;
      	int s[10];
      };
      struct comp{
      	int operator( )(node u,node v) {
      		return u.d>v.d;
      	}
      };
      priority_queue<node,vector<node>,comp > q;
      int cantor(int *p){//康托展开 
      	int k=0,ans=0;
      	for(register int i=1;i<=9;++i){
      		int sum=0,c=1;
      		for(register int j=i+1;j<=9;++j){
      			if(p[j]<p[i])sum++;
      			c*=(9-j+1);
      		}
      		ans+=c*sum;
      	}
      	return ans;
      }
      void output(int x){
      	if(pre[x]==-1)return;
      	output(pre[x]);
      	putchar(path[x]);
      }
      int value(int *x){
      	int sum=0;
      	for(register int i=1;i<=9;++i)if(x[i]!=9){
      		int u=(i-1)/3+1,v=(i-1)%3+1;
      		int u1=(x[i]-1)/3+1,v1=(x[i]-1)%3+1;
      		sum+=abs(u1-u)+abs(v1-v);
      	}
      	return sum;
      }
      int main( ){
      	int x,y,z,k=0,k1=0;
      	node now;
      	for(int i=1;i<=3;++i)
      		for(int j=1;j<=3;++j){
      			scanf("%s",c);
      			if(c[0]!='x'){
      				a[++k]=c[0]-'0';
      				now.s[++k1]=c[0]-'0';
      			}
      			else{
      				now.s[++k1]=9;now.pos=k1;
      			}
      	}
      	int ans=0;
      	for(int i=1;i<=8;++i)
      		for(int j=i+1;j<=8;++j)
      			if(a[j]<a[i])ans++;
      	if(ans%2==1){
      		printf("unsolvable\n");
      		return 0;
      	}
      	k=0;
      	now.st=cantor(now.s);
      	int t=0;
      	now.g=0;
      	now.d=value(now.s);
      	q.push(now);
      	pre[now.st]=-1;
      	vis[now.st]=1;
      	int flag=0;
      	while(q.size( )){
      		now=q.top( );q.pop( );
      		if(now.st==t){
      			flag=1;
      			break;
      		}
      		x=(now.pos-1)/3+1;//得到位置 
      		y=(now.pos-1)%3+1;
      		for(int i=0;i<4;++i){
      			int u=x+dr[i][0],v=y+dr[i][1];
      			if(u>3 || u<1 || v>3 || v<1)continue;
      			node tmp;
      			tmp=now;
      			tmp.s[(x-1)*3+y]=tmp.s[(u-1)*3+v];
      			tmp.s[(u-1)*3+v]=9;
      			tmp.st=cantor(tmp.s);
      			if(!vis[tmp.st]){
      				vis[tmp.st]=1;
      				tmp.pos=(u-1)*3+v;
      				tmp.g++;
      				tmp.d=tmp.g+value(tmp.s);
      				pre[tmp.st]=now.st;
      				path[tmp.st]=op[i];
      				q.push(tmp);
      			}
      		}
      	}
      	output(0);
      	return 0;
      }
      }
以及我的夭折代码:

//#include<bits/stdc++.h>
#include<algorithm>
#include <iostream>
#include  <fstream>
#include  <cstdlib>
#include  <cstring>
#include  <cassert>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <queue>
#include    <stack>
#include      <set>
#include      <map>
using namespace std;
#define P(a,b,c) make_pair(a,make_pair(b,c))
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n;i>=a;i--)
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef pair<int,pair<int,int> >pii;
typedef long long ll;
typedef unsigned long long ull;
const ll mod = 1000000007;
const int INF = 0x3f3f3f3f;
ll gcd(ll a, ll b) {
	return b ? gcd(b, a%b) : a;
}
template<class T>inline void gmax(T &A, T B) {
	(A<B)&&(A=B);//if(B>A)A=B;
}
template<class T>inline void gmin(T &A, T B) {
	(A>B)&&(A=B);//if(B<A)A=B;
}
template <class T>
inline bool scan_d(T &ret) {
	char c;
	int sgn;
	if(c=getchar(),c==EOF) return 0; //EOF
	while(c!='?'&&(c<'0'||c>'9')) c=getchar();
	sgn=(c=='?')?-1:1;
	ret=(c=='?')?0:(c-'0');
	while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
	ret*=sgn;
	return 1;
}
inline void outt(int x) {
	if(x>9) outt(x/10);
	putchar(x%10+'0');
}
map<int,int>mp;
int st=0;
int ed=123456780;
int G[10]= {33,11,12,13,21,22,23,31,32,0};
map<ll,ll>pre;
const int base=1e9;
int f(int s) {
	int sum=0;
	per(i,1,3) {
		per(j,1,3) {
			int t=s%10;
			s/=10;
			int x=G[t]/10;
			int y=G[t]%10;
			sum+=abs(i-x)+abs(j-y);
		}
	}
	return sum;
}
struct node {
	int s;
	int cnt;
	node(int _s=0,int _cnt=0):s(_s),cnt(_cnt) {};
	bool operator < (const node &a)const {
		return cnt>a.cnt;
	}
};
priority_queue<node>q;
int dir[4][2]= {{-1,0},{1,0},{0,-1},{0,1}};
bool ojbk(int x,int y) {
	if(x<=3&&x>0&&y<=3&&y>0)return true;
	return false;
}
void Swap(int &x,int &y) {
	x^=y;
	y^=x;
	x^=y;
}
ll get_state(int t[][4]) {
	int ss=0;
	rep(i,1,3) {
		rep(j,1,3) {
			ss=ss*10+t[i][j];
		}
	}
}
void dfs(ll ss) {
	if(pre[ss]==-1) {
		return ;
	}
	ll state=pre[ss];
	dfs(state%base);
	int D=state/base;
	int t[4][4];
//	state%=base;
//	per(i,1,3){
//		per(j,1,3){
//			t[i][j]=state%10;
//			state/=10;
//		}
//	}
//	rep(i,1,3){
//		rep(j,1,3){
//			cout<<t[i][j]<<" ";
//		}
//		cout<<endl;
//	}
//	cout<<endl;
/*
 2  3  4  1  5  x  7  6  8 
 dlurullddrurdllurdr
*/
	switch(D) {
		case 0:
			printf("u");
			break;
		case 1:
			printf("d");
			break;
		case 2:
			printf("l");
			break;
		case 3:
			printf("r");
			break;
	}
}
/* 1  2  3 
 x  4  6 
 7  5  8 
 1 3 2
 4 6 5
 X 7 8
 */
void A_() {
	while(!q.empty())q.pop();
	q.push(node(st,0+f(st)));
	node tmp;
	pre[st]=-1;
	while(!q.empty()) {
		tmp=q.top();
		q.pop();
		int state=tmp.s;
		int cnt=tmp.cnt;
		if(state==ed) {
			dfs(state);
			return;
		}
		int t[4][4];
		int ss=state;
		int x,y;
		per(i,1,3)
		per(j,1,3) {
			t[i][j]=ss%10,ss/=10;
			if(t[i][j]==0)x=i,y=j;
		}
		rep(i,0,3) {
			int xx=x+dir[i][0],yy=y+dir[i][1];
			if(ojbk(xx,yy)) {
				Swap(t[x][y],t[xx][yy]);
				
				ss=get_state(t);
				if(pre[(ll)ss]){
					Swap(t[x][y],t[xx][yy]);
					continue;
				}
				pre[(ll)ss]=(ll)(i*1e9+state);
				if(ss==ed){
					dfs(ss);return ;
				}
				q.push(node(ss,cnt+1-f(state)+f(ss)));
				
				Swap(t[x][y],t[xx][yy]);
			}
		}
	}
}
int main() {
	char s[10];
	int a[10];
	int cnt=0;
	rep(i,1,9) {
		scanf("%s", s);
		if(s[0]!='x') st=st*10+s[0]-'0',a[++cnt]=s[0]-'0';
		else st*=10;
	}
	if(st==ed)cout<<"";
	int ans=0;
	for(int i=1;i<=8;++i)
		for(int j=i+1;j<=8;++j)
			if(a[j]<a[i])ans++;
	if(ans%2==1)printf("unsolvable\n");
	else A_();
	return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注