描述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;
}