yonezzzet
10/15/2017 - 4:42 AM

15puzzle-astar.cpp

/* 
 * http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_13_C
 * A*
 */
#include <iostream>
#include <map>
#include <queue>
#include <vector>
#define N 4
#define N2 16
using namespace std;

vector<int> move_list[N2];
int dist[N2][N2];

class Game{
public:
  char board[N2];
  char w;
  vector<char> route;
  char mnh;

  bool operator < (const Game &other) const{
    return route.size()+mnh > other.route.size()+other.mnh;
  }
};
Game start;

vector<char> search(){
  priority_queue<Game> q;
  q.push(start);
  
  while(!q.empty()){
    Game g=q.top();q.pop();
    if(g.mnh==0) return g.route;

    for(int move:move_list[g.w]){
      if(g.route.size()>0 && g.route.back()==-move) continue;
      Game h=g;
      int to=h.w+move;
      h.mnh -= dist[to][h.board[to]-1];
      h.mnh += dist[h.w][h.board[to]-1];
      swap(h.board[h.w],h.board[to]);
      h.w = to;
      h.route.push_back(move);
      q.push(h); 
    }
  }
}

int solve(){
  vector<char> route=search();
  return route.size();
}

void initialize(){
  for(int i=0;i<N2;i++){
    if(i%N<N-1) move_list[i].push_back(1);
    if(i%N>0  ) move_list[i].push_back(-1);
    if(i/N<N-1) move_list[i].push_back(N);
    if(i/N>0  ) move_list[i].push_back(-N);
  }

  //i=board,j=piece-1
  for(int i=0;i<N2;i++){
    for(int j=0;j<N2;j++){
      dist[i][j] = abs(j%N-i%N) + abs(j/N-i/N);
    }
  }

  start.mnh=0;
  for(int i=0;i<N2;i++){
    if(i==start.w) continue;
    start.mnh += dist[i][start.board[i]-1];
  }
}
 
int main(){
  int tmp;
  for(int i=0;i<N2;i++){
    cin>>tmp;
    if(tmp==0){
      start.board[i]=N2;
      start.w=i;
    }else{
      start.board[i]=tmp;
    }
  }
  initialize();
  cout<<solve()<<endl;
}