M.Hiroi's Home Page
http://www.geocities.jp/m_hiroi/

Puzzle DE Programming

スライドパズル「Goat」:プログラムリスト

[ Home | Puzzle ]

●プログラムリスト1

/*
 * goat.c : スライドパズル Goat
 *
 *          Copyright (C) 2002 Makoto Hiroi
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define SIZE     12
#define B1        9
#define B2       10
#define MAX_MOVE 55

/* プロトタイプ宣言 */
void solve( int, int, int );

/* 隣接リスト */
const char adjacent[SIZE][5] = {
  1, 4,-1,-1,-1,    /* 0 */
  0, 2, 5,-1,-1,    /* 1 */
  1, 3, 6,-1,-1,    /* 2 */
  2, 7,-1,-1,-1,    /* 3 */
  0, 5, 8,-1,-1,    /* 4 */
  1, 4, 6, 9,-1,    /* 5 */
  2, 5, 7,10,-1,    /* 6 */
  3, 6,11,-1,-1,    /* 7 */
  4, 9,-1,-1,-1,    /* 8 */
  5, 8,10,-1,-1,    /* 9 */
  6, 9,11,-1,-1,    /* 10*/
  7,10,-1,-1,-1,    /* 11*/
};

/* スタート */
const char init_state[SIZE] = {
  1, 8,B1,B2,
  2, 0, 7, 5,
  3, 8, 4, 6,
};

/* ゴール */
const char final_state[SIZE] = {
  1, 8,B1,B2,
  2, 5, 7, 0,
  3, 8, 4, 6,
};

/* 盤面 */
char board[SIZE];

/* 動かした位置, 移動先の位置 */
char move_position[MAX_MOVE + 1];
char moveto_position[MAX_MOVE + 1];

/* 計測用 */
int start;

/* 初期化 */
void init( void )
{
  memcpy( board, init_state, SIZE );
  move_position[0] = -1;
  moveto_position[0] = -1;
}

/* 盤面の表示 */
void print_board( char *b )
{
  const static char *piece_data[11] = {
    "□", "┌", "│", "└", "┘", "羊", "狼", "‖", "─", "┐", "  ",
  };
  int i;
  for( i = 0; i < SIZE; i++ ){
    printf( "%s", piece_data[ b[i] ] );
    if( i == 3 || i == 7 || i == 11 ) printf("\n");
  }
  printf("\n");
}

/* 手順を表示 */
void print_answer( int m )
{
  int i;
  char work[SIZE];
  memcpy( work, init_state, SIZE );
  print_board( work );
  for( i = 1; i <= m; i++ ){
    int from = move_position[i];
    int to   = moveto_position[i];
    if( work[from] == B1 ){
      work[to] = B1;
      work[to + 1] = B2;
      work[from] = 0;
    } else if( work[from] == B2 ){
      work[to] = B2;
      work[to - 1] = B1;
      work[from] = 0;
    } else {
      work[to]   = work[from];
      work[from] = 0;
    }
    print_board( work );
  }
  printf("\n時間 %d\n", clock() - start );
  exit( 0 );
}

/* 大きな駒を動かす */
void move_big_piece( int limit, int move, int space, int piece )
{
  int new_space, new_place;
  if( piece == B1 ){
    /* 左へ */
    board[space] = B1;
    board[space + 1] = B2;
    board[space + 2] = 0;
    new_space = space + 2;
    new_place = space + 1;
  } else {
    /* 右へ */
    board[space] = B2;
    board[space - 1] = B1;
    board[space - 2] = 0;
    new_space = space - 2;
    new_place = space - 1;
  }
  move_position[move + 1] = new_space;
  moveto_position[move + 1] = new_place;
  /* 再帰呼び出し */
  solve( limit, move + 1, new_space );
  /* 元に戻す */
  if( piece == B1 ){
    board[space] = 0;
    board[space + 1] = B1;
    board[space + 2] = B2;
  } else {
    board[space] = 0;
    board[space - 1] = B2;
    board[space - 2] = B1;
  }
}


/* 反復深化による探索 */
void solve( int limit, int move, int space )
{
  if( move == limit ){
    if( !memcmp( board, final_state, SIZE ) ){
      print_answer( move );
    }
  } else {
    int i, j;
    for( i = 0; (j = adjacent[space][i]) != -1; i++ ){
      int piece = board[j];
      if( moveto_position[move] == j ) continue;
      if( piece == B1 || piece == B2 ){
        if( space < 4 ){
          /* 移動可能 */
          move_big_piece( limit, move, space, piece );
        }
      } else {
        /* 移動する */
        board[space] = piece;
        board[j] = 0;
        move_position[move + 1] = j;
        moveto_position[move + 1] = space;
        /* 再帰呼び出し */
        solve( limit, move + 1, j );
        /* 元に戻す */
        board[space] = 0;
        board[j] = piece;
      }
    }
  }
}

int main()
{
  int limit;
  start = clock();
  init();
  for( limit = 1; limit < MAX_MOVE; limit++ ){
    printf("***** %d 手目を探索中 *****\n", limit );
    solve( limit, 0, 5 );
  }
  return 0;
}

戻る


●プログラムリスト2

/*
 * goat_max.c : スライドパズル Goat
 *              最長手数の局面を求める
 *
 *              Copyright (C) 2002 Makoto Hiroi
 */ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define TRUE   1
#define FALSE  0
#define SIZE  12
#define B1     9
#define B2    10
#define NIL   (-1)
#define HVAL  1814400

/* 状態数  */
#define MAX   5443200

/* 隣接リスト */
const char adjacent[SIZE][5] = {
  1, 4,-1,-1,-1,    /* 0 */
  0, 2, 5,-1,-1,    /* 1 */
  1, 3, 6,-1,-1,    /* 2 */
  2, 7,-1,-1,-1,    /* 3 */
  0, 5, 8,-1,-1,    /* 4 */
  1, 4, 6, 9,-1,    /* 5 */
  2, 5, 7,10,-1,    /* 6 */
  3, 6,11,-1,-1,    /* 7 */
  4, 9,-1,-1,-1,    /* 8 */
  5, 8,10,-1,-1,    /* 9 */
  6, 9,11,-1,-1,    /* 10*/
  7,10,-1,-1,-1,    /* 11*/
};

/* 初期状態 */
char init_state[SIZE] = {
  1, 8,B1,B2,
  2, 5, 7, 0,
  3, 8, 4, 6,
};

/* 手数を格納するテーブル */
char *check_table;

/* 数値表 */
const int table[8] ={
  181440,   /* 9 * 8 * 7 * 6 * 5 * 4 * 3 */
  20160,    /* 8 * 7 * 6 * 5 * 4 * 3 */
  2520,     /* 7 * 6 * 5 * 4 * 3 */
  360,      /* 6 * 5 * 4 * 3 */
  60,       /* 5 * 4 * 3 */
  12,       /* 4 * 3 */
  3,        /* 3 */
  1,
};

/* 盤面を数値に変換 */
int board_to_number( char *board )
{
  int buffer[8];       /* 0 - 7 までの位置を格納 */
  int i, j, b1, value = 0;
  for( i = 0; i < SIZE; i++ ){
    int p = board[i];
    if( p < 8 ){
      buffer[p] = i;
    } else if( p == B1 ){
      b1 = i;
    }
  }
  /* 補正 */
  for( i = 0; i < 8; i++ ){
    if( buffer[i] > b1 ) buffer[i] -= 2;
  }
  for( i = 0; i < 8; i++ ){
    value += table[i] * buffer[i];
    for( j = i + 1; j < 8; j++ ){
      if( buffer[i] < buffer[j] ) buffer[j]--;
    }
  }
  return b1 * HVAL + value;
}

/* 数値を盤面に変換:空き場所の位置を返す */
int number_to_board( int num, char *board )
{
  int i, j, b1;
  char buffer[8];
  b1 = num / HVAL;
  num %= HVAL;
  memset( board, 8, SIZE );
  board[b1] = B1;
  board[b1 + 1] = B2;
  for( i = 0; i < 7; i++ ){
    buffer[i] = num / table[i];
    num %= table[i];
  }
  buffer[i] = num;
  for( i = 6; i >= 0; i-- ){
    for( j = i + 1; j < 8; j++ ){
      if( buffer[i] <= buffer[j] ) buffer[j]++;
    }
  }
  /* 補正 */
  for( i = 0; i < 8; i++ ){
    if( buffer[i] >= b1 ) buffer[i] += 2;
  }
  for( i = 0; i < 8; i++ ){
    board[ buffer[i] ] = i;
  }
  return buffer[0];
}

/* 初期化 */
void init( void )
{
  check_table = malloc( MAX );
  if( check_table == NULL ){
    fprintf(stderr, "out of memory\n"); exit( 1 );
  }
  memset( check_table, NIL, MAX );
}

/* 駒を移動する */
int move_piece( int num, int move )
{
  char board[SIZE];
  int  c = 0;                   /* 展開した局面数 */
  int  s, i, n, new_num;

  s = number_to_board( num, board );
  for( i = 0; (n = adjacent[s][i]) != -1; i++ ){
    /* 移動 */
    int piece = board[n];
    if( piece == B1 || piece == B2 ){
      if( s >= 4 ) continue; /* 左右しか移動できない */
      /* 大駒の移動 */
      if( piece == B1 ){
        board[s] = B1;
        board[s + 1] = B2;
        board[s + 2] = 0;
      } else {
        board[s] = B2;
        board[s - 1] = B1;
        board[s - 2] = 0;
      }
    } else {
      board[s] = board[n];
      board[n] = 0;
    }
    new_num = board_to_number( board );
    if( check_table[new_num] == NIL ){
      /* 登録 */
      check_table[new_num] = move;
      c++;
    }
    /* 元に戻す */
    if( piece == B1 ){
      board[s] = 0;
      board[s + 1] = B1;
      board[s + 2] = B2;
    } else if( piece == B2 ){
      board[s] = 0;
      board[s - 1] = B2;
      board[s - 2] = B1;
    } else {
      board[n] = board[s];
      board[s] = 0;
    }
  }
  return c;
}

void print_board( char *b )
{
  const static char *piece_data[11] = {
    "□", "┌",  "│", "└", "┘", "羊", "狼", "‖", "─", "┐", "  ",
  };
  int i;
  for( i = 0; i < SIZE; i++ ){
    printf( "%s", piece_data[ b[i] ] );
    if( i == 3 || i == 7 || i == 11 ) printf("\n");
  }
  printf("\n");
}

/* 最長手数の局面を表示 */
void print_answer( int move )
{
  int i;
  char board[SIZE];
  for( i = 0; i < MAX; i++ ){
    if( check_table[i] == move ){
      number_to_board( i, board );
      print_board( board );
    }
  }
}

/* 探索 */
void search( void )
{
  int num, total = 1, move = 1;

  /* 初手を展開 */
  num = board_to_number( init_state );
  check_table[num] = 0;             /* 初期値 */
  total += move_piece( num, move );
  printf("%2d手 --- %d個\n", move, total );

  /* 2手目以降の展開 */
  for( ; ; move++ ){
    int i, c = 0;
    for( i = 0; i < MAX; i++ ){
      if( check_table[i] == move ){
        c += move_piece( i, move + 1 );
      }
    }
    if( c == 0 ) break;
    printf("%2d手 --- %d個\n", move + 1, c );
    total += c;
  }
  print_answer( move );
  printf("合計 %d 個\n", total );
}

int main()
{
  int start, end;
  printf("***** 初期状態 *****\n");
  print_board( init_state );
  printf("********************\n");
  start = clock();
  init();
  search();
  end = clock();
  printf("時間 %d\n", end - start );
  return 0;
}

戻る


●プログラムリスト3

/*
 * goat2.c : スライドパズル Goat
 *           最長手数の局面を反復深化で解く
 *
 *           Copyright (C) 2002 Makoto Hiroi
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define SIZE     12
#define B1        9
#define B2       10
#define MAX_MOVE 55

/* プロトタイプ宣言 */
void solve( int, int, int, int );

/* 隣接リスト */
const char adjacent[SIZE][5] = {
  1, 4,-1,-1,-1,    /* 0 */
  0, 2, 5,-1,-1,    /* 1 */
  1, 3, 6,-1,-1,    /* 2 */
  2, 7,-1,-1,-1,    /* 3 */
  0, 5, 8,-1,-1,    /* 4 */
  1, 4, 6, 9,-1,    /* 5 */
  2, 5, 7,10,-1,    /* 6 */
  3, 6,11,-1,-1,    /* 7 */
  4, 9,-1,-1,-1,    /* 8 */
  5, 8,10,-1,-1,    /* 9 */
  6, 9,11,-1,-1,    /* 10*/
  7,10,-1,-1,-1,    /* 11*/
};

/* 初期状態
 *
 *  狼‖┐
 *  ┘羊│─
 *  □─└┌
 */
const char init_state[SIZE] = {
  6, 7,B1,B2,
  4, 5, 2, 8,
  0, 8, 3, 1,
};

/* ゴール */
const char final_state[SIZE] = {
  1, 8,B1,B2,
  2, 5, 7, 0,
  3, 8, 4, 6,
};

/* 移動手数 */
int distance[11][SIZE] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* dummy */
  0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5,    /* 1 */
  1, 2, 3, 4, 0, 1, 2, 3, 1, 2, 3, 4,    /* 2 */
  2, 3, 4, 5, 1, 2, 3, 4, 0, 1, 2, 3,    /* 3 */
  4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1,    /* 4 */
  2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3,    /* 5 */
  5, 4, 3, 2, 4, 3, 2, 1, 3, 2, 1, 0,    /* 6 */
  3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2,    /* 7 */
  1, 0, 1, 2, 2, 1, 2, 3, 1, 0, 1, 2,    /* 8 */
  2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,    /* 9 */
  3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* 10 */
};

/* 盤面 */
char board[SIZE];

/* 動かした位置, 移動先の位置 */
char move_position[MAX_MOVE];
char moveto_position[MAX_MOVE];

/* 計測用 */
int start;

/* 下限値を求める */
int calc_lower_value( const char *board )
{
  int i, j, d = 0;
  /* B2 は除外する */
  for( i = 0; i < SIZE; i++ ){
    j = board[i];
    if( j > 0 && j != B2 ) d += distance[j][i];
  }
  return d;
}

/* 初期化 */
void init( void )
{
  memcpy( board, init_state, SIZE );
  move_position[0] = -1;
  moveto_position[0] = -1;
}

/* 盤面を表示する */
void print_board( char *b )
{
  const static char *piece_data[11] = {
    "□", "┌",  "│", "└", "┘", "羊", "狼", "‖", "─", "┐", "  ",
  };
  int i;
  for( i = 0; i < SIZE; i++ ){
    printf( "%s", piece_data[ b[i] ] );
    if( i == 3 || i == 7 || i == 11 ) printf("\n");
  }
  printf("\n");
}

/* 手順を表示 */
void print_answer( int m )
{
  int i;
  char work[SIZE];
  memcpy( work, init_state, SIZE );
  print_board( work );
  for( i = 1; i <= m; i++ ){
    int from = move_position[i];
    int to   = moveto_position[i];
    if( work[from] == B1 ){
      work[to] = B1;
      work[to + 1] = B2;
      work[from] = 0;
    } else if( work[from] == B2 ){
      work[to] = B2;
      work[to - 1] = B1;
      work[from] = 0;
    } else {
      work[to]   = work[from];
      work[from] = 0;
    }
    print_board( work );
  }
  printf("\n時間 %d\n", clock() - start );
  exit( 0 );
}

/* 大きな駒を動かす */
void move_big_piece( int limit, int move, int space, int piece, int low )
{
  int new_space, new_place, new_low;
  if( piece == B1 ){
    /* 左へ */
    board[space] = B1;
    board[space + 1] = B2;
    board[space + 2] = 0;
    new_space = space + 2;
    new_place = space + 1;
    new_low   = low + 1;
    
  } else {
    /* 右へ */
    board[space] = B2;
    board[space - 1] = B1;
    board[space - 2] = 0;
    new_space = space - 2;
    new_place = space - 1;
    new_low   = low - 1;
  }
  move_position[move + 1] = new_space;
  moveto_position[move + 1] = new_place;
  /* 下限値による枝刈り */
  if( new_low + move <= limit ){
    solve( limit, move + 1, new_space, new_low );
  }
  /* 元に戻す */
  if( piece == B1 ){
    board[space] = 0;
    board[space + 1] = B1;
    board[space + 2] = B2;
  } else {
    board[space] = 0;
    board[space - 1] = B2;
    board[space - 2] = B1;
  }
}

/* 反復深化+下限値枝刈り法による探索 */
void solve( int limit, int move, int space, int low )
{
  if( move == limit ){
    if( !memcmp( board, final_state, SIZE ) ){
      print_answer( move );
    }
  } else {
    int i, j, new_low;
    for( i = 0; (j = adjacent[space][i]) != -1; i++ ){
      int piece = board[j];
      if( moveto_position[move] == j ) continue;
      if( piece == B1 || piece == B2 ){
        if( space < 4 ){
          /* 大きな駒を動かす */
          move_big_piece( limit, move, space, piece, low );
        }
      } else {
        /* 移動する */
        board[space] = piece;
        board[j] = 0;
        move_position[move + 1] = j;
        moveto_position[move + 1] = space;
        new_low = low - distance[piece][j] + distance[piece][space];
        /* 下限値による枝刈り */
        if( new_low + move <= limit ){
          solve( limit, move + 1, j, new_low );
        }
        /* 元に戻す */
        board[space] = 0;
        board[j] = piece;
      }
    }
  }
}

int main()
{
  int limit, low, space;
  low = calc_lower_value( init_state );
  /* 空き場所を探す */
  for( space = 0; space < SIZE; space++ ){
    if( !init_state[space] ) break;
  }
  start = clock();
  init();
  for( limit = low ; limit < MAX_MOVE; limit++ ){
    fprintf( stderr, "***** %d 手目を探索中 *****\n", limit );
    solve( limit, 0, space, low );
  }
  return 0;
}

戻る


●プログラムリスト4

/*
 * goat3.c : スライドパズル Goat
 *           最長手数の局面を反復深化で解く
 *           駒 ─ を区別することで下限値を改善する
 *
 *           Copyright (C) 2002 Makoto Hiroi
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define SIZE     12
#define B1        9
#define B2       10
#define MAX_MOVE 55

/* プロトタイプ宣言 */
void solve( int, int, int, int );

/* 隣接リスト */
const char adjacent[SIZE][5] = {
  1, 4,-1,-1,-1,    /* 0 */
  0, 2, 5,-1,-1,    /* 1 */
  1, 3, 6,-1,-1,    /* 2 */
  2, 7,-1,-1,-1,    /* 3 */
  0, 5, 8,-1,-1,    /* 4 */
  1, 4, 6, 9,-1,    /* 5 */
  2, 5, 7,10,-1,    /* 6 */
  3, 6,11,-1,-1,    /* 7 */
  4, 9,-1,-1,-1,    /* 8 */
  5, 8,10,-1,-1,    /* 9 */
  6, 9,11,-1,-1,    /* 10*/
  7,10,-1,-1,-1,    /* 11*/
};

/* 初期状態
 *
 *  狼‖┐
 *  ┘羊│─
 *  □─└┌
 */
const char init_state[SIZE] = {
  6, 7,B1,B2,  /* 5, 2, 0, 0 */
  4, 5, 2, 8,  /* 3, 0, 2, 3 */
  0,11, 3, 1,  /* 0, 0, 2, 5 */
};

/* ゴール */
const char final_state[SIZE] = {
  1, 8,B1,B2,
  2, 5, 7, 0,
  3,11, 4, 6,
};

/* 移動手数 */
int distance[12][SIZE] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* dummy */
  0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5,    /* 1 */
  1, 2, 3, 4, 0, 1, 2, 3, 1, 2, 3, 4,    /* 2 */
  2, 3, 4, 5, 1, 2, 3, 4, 0, 1, 2, 3,    /* 3 */
  4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1,    /* 4 */
  2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3,    /* 5 */
  5, 4, 3, 2, 4, 3, 2, 1, 3, 2, 1, 0,    /* 6 */
  3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2,    /* 7 */
  1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4,    /* 8 */
  2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,    /* 9 */
  3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* 10 */
  3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2,    /* 11 */
};

/* 盤面 */
char board[SIZE];

/* 動かした位置, 移動先の位置 */
char move_position[MAX_MOVE];
char moveto_position[MAX_MOVE];

/* 計測用 */
int start;

/* 下限値を求める */
int calc_lower_value( const char *board )
{
  int i, j, d = 0;
  /* B2 は除外する */
  for( i = 0; i < SIZE; i++ ){
    j = board[i];
    if( j > 0 && j != B2 ) d += distance[j][i];
  }
  return d;
}

/* 初期化 */
void init( void )
{
  memcpy( board, init_state, SIZE );
  move_position[0] = -1;
  moveto_position[0] = -1;
}


/* 盤面を表示する */
void print_board( char *b )
{
  const static char *piece_data[12] = {
    "□", "┌",  "│", "└", "┘", "羊", "狼", "‖", "─", "┐", "  ", "─",
  };
  int i;
  for( i = 0; i < SIZE; i++ ){
    printf( "%s", piece_data[ b[i] ] );
    if( i == 3 || i == 7 || i == 11 ) printf("\n");
  }
  printf("\n");
}


/* 手順を表示 */
void print_answer( int m )
{
  int i;
  char work[SIZE];
  memcpy( work, init_state, SIZE );
  print_board( work );
  for( i = 1; i <= m; i++ ){
    int from = move_position[i];
    int to   = moveto_position[i];
    if( work[from] == B1 ){
      work[to] = B1;
      work[to + 1] = B2;
      work[from] = 0;
    } else if( work[from] == B2 ){
      work[to] = B2;
      work[to - 1] = B1;
      work[from] = 0;
    } else {
      work[to]   = work[from];
      work[from] = 0;
    }
    print_board( work );
  }
  printf("\n時間 %d\n", clock() - start );
  exit( 0 );
}

/* 大きな駒を動かす */
void move_big_piece( int limit, int move, int space, int piece, int low )
{
  int new_space, new_place, new_low;
  if( piece == B1 ){
    /* 左へ */
    board[space] = B1;
    board[space + 1] = B2;
    board[space + 2] = 0;
    new_space = space + 2;
    new_place = space + 1;
    new_low   = low + 1;
    
  } else {
    /* 右へ */
    board[space] = B2;
    board[space - 1] = B1;
    board[space - 2] = 0;
    new_space = space - 2;
    new_place = space - 1;
    new_low   = low - 1;
  }
  move_position[move + 1] = new_space;
  moveto_position[move + 1] = new_place;
  /* 下限値による枝刈り */
  if( new_low + move <= limit ){
    solve( limit, move + 1, new_space, new_low );
  }
  /* 元に戻す */
  if( piece == B1 ){
    board[space] = 0;
    board[space + 1] = B1;
    board[space + 2] = B2;
  } else {
    board[space] = 0;
    board[space - 1] = B2;
    board[space - 2] = B1;
  }
}

/* 反復深化による探索 */
void solve( int limit, int move, int space, int low )
{
  if( move == limit ){
    if( !memcmp( board, final_state, SIZE ) ){
      /* 見つけたよ */
      print_answer( move );
    }
  } else {
    int i, j, new_low;
    for( i = 0; (j = adjacent[space][i]) != -1; i++ ){
      int piece = board[j];
      if( moveto_position[move] == j ) continue;
      if( piece == B1 || piece == B2 ){
        if( space < 4 ){
          /* 移動可能 */
          move_big_piece( limit, move, space, piece, low );
        }
      } else {
        /* 移動する */
        board[space] = piece;
        board[j] = 0;
        move_position[move + 1] = j;
        moveto_position[move + 1] = space;
        new_low = low - distance[piece][j] + distance[piece][space];
        /* 下限値による枝刈り */
        if( new_low + move <= limit ){
          solve( limit, move + 1, j, new_low );
        }
        /* 元に戻す */
        board[space] = 0;
        board[j] = piece;
      }
    }
  }
}

int main()
{
  int limit, low, space;
  low = calc_lower_value( init_state );
  /* 空き場所を探す */
  for( space = 0; space < SIZE; space++ ){
    if( !init_state[space] ) break;
  }
  start = clock();
  init();
  for( limit = low ; limit < MAX_MOVE; limit++ ){
    fprintf( stderr, "***** %d 手目を探索中 *****\n", limit );
    solve( limit, 0, space, low );
  }
  return 0;
}

戻る


Copyright (C) 2002-2003 Makoto Hiroi
All rights reserved.

[ Home | Puzzle ]