The goal of the 15 puzzle problem is to complete pieces on 4×4
cells where one of the cells is empty space.
In this problem, the space is represented by 0 and pieces are represented by integers from 1 to 15 as shown below.
1 2 3 4 6 7 8 0 5 10 11 12 9 13 14 15
You can move a piece toward the empty space at one step. Your goal is to make the pieces the following configuration in the shortest move (fewest steps).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0
Write a program which reads an initial state of the puzzle and prints the fewest steps to solve the puzzle.
Input
The 4×4
integers denoting the pieces or space are given.
Output
Print the fewest steps in a line.
Constraints
- The given puzzle is solvable in at most 45 steps.
Sample Input
1 2 3 4 6 7 8 0 5 10 11 12 9 13 14 15
Sample Output
8
用A*会内存超限
#include<stdio.h>
#include<string.h>
#include<queue>
#include<string>
#include<map>
#include<math.h>
#include<algorithm>
using namespace std;
#define N 16
int mp[N][N],nx[4][2]= {0,-1,-1,0,0,1,1,0};
struct node
{
string s;
int space,md,cost;
int ans;
bool operator < (const node &a)const
{
return a.ans < ans;
}
};
int getallmd(node a)
{
int sum=0;
for(int i=0; i<N; i++)
{
if(a.s[i] == N+'0') continue;
sum+=mp[i][a.s[i]-'0'-1];
}
return sum;
}
void bfs(node a)
{
node now,tmp;
priority_queue<node>Q;
a.cost=0;
a.md=a.ans=getallmd(a);
map<string,int>ms;
ms[a.s]=1;
Q.push(a);
while(!Q.empty())
{
now=Q.top();
Q.pop();
if(now.md==0)
{
printf("%d\n",now.cost);
return ;
}
int x=now.space/4;
int y=now.space%4;
for(int i=0; i<4; i++)
{
int tx=x+nx[i][0];
int ty=y+nx[i][1];
if(tx<0 || ty<0 || tx>=4 || ty>=4) continue;
tmp=now;
tmp.md-=mp[tx*4+ty][tmp.s[tx*4+ty]-'0'-1];
tmp.md+=mp[x*4+y][tmp.s[tx*4+ty]-'0'-1];
swap(tmp.s[x*4+y],tmp.s[tx*4+ty]);
tmp.space=tx*4+ty;
tmp.cost++;
tmp.ans=tmp.cost+tmp.md;
if(!ms[tmp.s])
{
ms[tmp.s]=1;
Q.push(tmp);
}
}
}
}
int main()
{
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
mp[i][j]=abs(i/4-j/4)+abs(i%4-j%4);
node a;
int c;
for(int i=0; i<N; i++)
{
scanf("%d",&c);
if(c==0)
{
a.space=i;
c=16;
}
a.s+=c+'0';
}
bfs(a);
return 0;
}
用IDA*实现
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define N 16
int mp[N][N],nx[4][2]= {0,-1,-1,0,0,1,1,0};
int ans,limit/*(深度限制)*/;
struct node
{
int space,md;
int s[N];
};
node state;
int getallmd(node a)
{
int sum=0;
for(int i=0; i<N; i++)
{
if(a.s[i] == N) continue;
sum+=mp[i][a.s[i]-1];
}
return sum;
}
int dfs(int step,int prev)
{
if(state.md==0)
{
ans=step;
return 1;
}
if(step+state.md > limit)
return 0;
int x=state.space/4;
int y=state.space%4;
node tmp=state;
for(int i=0; i<4; i++)
{
int tx=x+nx[i][0];
int ty=y+nx[i][1];
if(tx<0 || ty<0 || tx>=4 || ty>=4 || abs(prev-i)==2) continue; //abs判断是否返回到上一次的出发点
tmp=state;
state.md-=mp[tx*4+ty][state.s[tx*4+ty]-1];
state.md+=mp[x*4+y][state.s[tx*4+ty]-1];
swap(state.s[x*4+y],state.s[tx*4+ty]);
state.space=tx*4+ty;
if(dfs(step+1,i))
return 1;
state=tmp;
}
return 0;
}
void check(node a)
{
a.md=getallmd(a);
for(limit=a.md; limit<=100; limit++)
{
state=a;
if(dfs(0,-100))
{
printf("%d\n",ans);
return ;
}
}
return ;
}
int main()
{
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
mp[i][j]=abs(i/4-j/4)+abs(i%4-j%4);
node a;
int c;
for(int i=0; i<N; i++)
{
scanf("%d",&a.s[i]);
if(a.s[i]==0)
{
a.s[i]=16;
a.space=i;
}
}
check(a);
return 0;
}
IDA* 不用结构体
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 16
int mp[N][N],ans,flag;
int nx[4][2]= {0,-1,-1,0,0,1,1,0};
int check()
{
int sum=0;
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
{
if(mp[i][j]!=i*4+j+1 && mp[i][j])
sum+=abs((mp[i][j]-1)/4-i)+abs((mp[i][j]-1)%4-j);
}
return sum;
}
void dfs(int x,int y,int res,int prev)
{
if(res+check() > ans || flag) return ;
if(check()==0)
{
flag=1;
return ;
}
for(int i=0; i<4; i++)
{
int tx=x+nx[i][0];
int ty=y+nx[i][1];
if(tx<0 || tx>=4 || ty<0 ||ty>=4 || abs(prev-i)==2) continue;
swap(mp[x][y],mp[tx][ty]);
dfs(tx,ty,res+1,i);
swap(mp[x][y],mp[tx][ty]);
}
}
int main()
{
int x,y;
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
{
scanf("%d",&mp[i][j]);
if(!mp[i][j])
{
x=i;
y=j;
}
}
ans=check();
flag=0;
while(1)
{
dfs(x,y,0,-100);
if(flag)
{
printf("%d\n",ans);
break;
}
ans++;
}
return 0;
}