質問

って練習するために、グ競争、私は彼に質問を私は完全に戸惑います。しかし、私としても、コンセプトを学ぶべき現在ではなくクロス指ることはありません。

基本的には、これはナイト作品をチェス。お二つの入力:開始位置と終了す。この目的は、その計算および印刷の最短経路のナイトで取得する対象の立地です。

私は初めまでの最短経路っぽいものを、私は全く身に覚えがないのですが場所を知るのが始まります。どの論理のない雇用への取り組み。

P.S.まず妥当性、っていただきたいの騎士の通常の移動も可能となったこの四隅に角形成される(潜在的に)八移動し、ナイトでは、これらのセンターのスクエアの騎士っています。

役に立ちましたか?

解決

お持ちのグラフのように、で利用可能なすべての動きを接続(value=1)、不動切断(value=0)の疎行列のようなもの:

(a1,b3)=1,
(a1,c2)=1,
  .....

の最短経路の二つのポイントのグラフにすることができ http://en.wikipedia.org/wiki/Dijkstra's_algorithm

擬似コードからのwikipediaページ:

function Dijkstra(Graph, source):
   for each vertex v in Graph:           // Initializations
       dist[v] := infinity               // Unknown distance function from source to v
       previous[v] := undefined          // Previous node in optimal path from source
   dist[source] := 0                     // Distance from source to source
   Q := the set of all nodes in Graph
   // All nodes in the graph are unoptimized - thus are in Q
   while Q is not empty:                 // The main loop
       u := vertex in Q with smallest dist[]
       if dist[u] = infinity:
          break                         // all remaining vertices are inaccessible from source
       remove u from Q
       for each neighbor v of u:         // where v has not yet been removed from Q.
           alt := dist[u] + dist_between(u, v) 
           if alt < dist[v]:             // Relax (u,v,a)
               dist[v] := alt
               previous[v] := u
   return dist[]

編集:

  1. としてmoronとの http://en.wikipedia.org/wiki/A*_algorithm 可能になります。
  2. インターネットには想像もつかな、 事前計算して、距離 保存してください、8×8のフルマトリックスものだとしたら、その不正な行為が発覚した場合, 作品のみでの問題 は小さい。るが、時には大会 チェック速度をどのようにプログラム 運行しています。
  3. その要点はその準備をしている のためのプログラミング競争を常に把握しておく必要があ 共通のアルゴリズムを含むDijkstraます。荷物状況については直接読む Introduction to Algorithms ISBN0-262-03384-4.やってみよう http://en.wikipedia.org/wiki/List_of_algorithms

他のヒント

編集: 参照サイモンの応答, は、固定式を示します。

実際にはO(1)式

このイメージするためのシェイプを作ってみました可視化する(マスブックトークで"和菓子のアン"でNth 移動した塗装と同じ色)を識別することができます。Knight's Move

きの通知のパターン。

見ることができるのは、パターンで見つかの機能 f( x , y ) この数を返します。動に必要になっていくことになるでしょうスクエア ( 0 , 0 ) るスクエア ( x , y )

しかし式ることが 0 <= y <= x

int f( int x , int y )
{
    int delta = x - y;

    if( y > delta )
        return 2 * ( ( y - delta ) / 3 ) + delta;
    else
        return delta - 2 * ( ( delta - y ) / 4 );
}

注意:この問いた SACO2007年日1
およびソリューション こちらの

こちらは正しいO(1)溶液に、ものの場合においてはナイトのように移動するチェスナイトのみで、無限のチェスボード:

https://jsfiddle.net/graemian/5qgvr1ba/11/

のコンデンサーマイクとこのパターン発生するときに描画します。図の下の方には最低限の数の移動に必要な数字を達成するためにスクエアを使用することができ幅優先探索す):

Patterns

ので、ソリューションが左右対称の軸のdiagonals、私だけに描かれたのx>=0y>=xす。

の左側のブロックの開始位置の数のブロックを代表する最小数の動きの方がブロックとなります。

が3パターンを知

  • のincrementing青色縦型群4
  • "主"赤diagonals(実行プログラムインストール前に右下のようにバックスラッシュ)
  • の"第二次"グリーンdiagonals(同一方向に赤)

(ただくには、両セットdiagonalsとしてトップ左下にする小パッケージです。この定数の移動数です。の左側の右上diagonalsります。)

できる式を導出します。黄色のブロックは特別な例です。その解決につなが

function getMoveCountO1(x, y) {

    var newXY = simplifyBySymmetry(x, y);

    x = newXY.x;
    y = newXY.y;

    var specialMoveCount = getSpecialCaseMoveCount(x ,y);

    if (specialMoveCount !== undefined)
        return specialMoveCount;

    else if (isVerticalCase(x, y))
        return getVerticalCaseMoveCount(x ,y);

    else if (isPrimaryDiagonalCase(x, y))
        return getPrimaryDiagonalCaseMoveCount(x ,y);

    else if (isSecondaryDiagonalCase(x, y))
        return getSecondaryDiagonalCaseMoveCount(x ,y);

}

と、苦労しているの垂直グループ

function isVerticalCase(x, y) {

    return y >= 2 * x;

}

function getVerticalCaseMoveCount(x, y) {

    var normalizedHeight = getNormalizedHeightForVerticalGroupCase(x, y);

    var groupIndex = Math.floor( normalizedHeight / 4);

    var groupStartMoveCount = groupIndex * 2 + x;

    return groupStartMoveCount + getIndexInVerticalGroup(x, y);

}

function getIndexInVerticalGroup(x, y) {

    return getNormalizedHeightForVerticalGroupCase(x, y) % 4;

}

function getYOffsetForVerticalGroupCase(x) {

    return x * 2;

}

function getNormalizedHeightForVerticalGroupCase(x, y) {

    return y - getYOffsetForVerticalGroupCase(x);

}

の怒その他の例です。

ん、ありがとうございまはより優雅なパターンだったので買ってきた?その場合、プログラムを手がかりにします。特に、通知の一部に斜めのパターンには青の垂直の場合、がんを探します。しかし、このソリューションも満足にはO(1)に与えます。

非常に興味深い問題をいたしました。など、見所がたくさんありソフトウェア技術者た今は頑張るしかないの解析的一般式(O(1) time and space complexity この設定に SACO2007年日1 .

まず評価したいと思い Graeme Pyle のためのも可視化する手助けとなっ固定式です。

何らかの理由ものための簡略化や美しさは間違い)に移転 minus サイン入り floor オペレーターといった間違い式 floor(-a) != -floor(a) for any a.

ここでは、正しい解析式:

var delta = x-y;
if (y > delta) {
    return delta - 2*Math.floor((delta-y)/3);
} else {
    return delta - 2*Math.floor((delta-y)/4);
}

式のため、すべての(x,y)のペア(適用後の軸対角対称性)を除く(1,0)、(2,2)のコーナーの場合、満たしていないパターンおよびハードコードは以下のスニペット:

function distance(x,y){
     // axes symmetry 
     x = Math.abs(x);
     y = Math.abs(y);
     // diagonal symmetry 
     if (x < y) {
        t = x;x = y; y = t;
     }
     // 2 corner cases
     if(x==1 && y == 0){
        return 3;
     }
     if(x==2 && y == 2){
        return 4;
     }
    
    // main formula
    var delta = x-y;
		if(y>delta){
  		return delta - 2*Math.floor((delta-y)/3);
  	}
  	else{
  		return delta - 2*Math.floor((delta-y)/4);
  	}
}


$body = $("body");
var html = "";
for (var y = 20; y >= 0; y--){
	html += '<tr>';
	for (var x = 0; x <= 20; x++){
  	html += '<td style="width:20px; border: 1px solid #cecece" id="'+x+'_'+y+'">'+distance(x,y)+'</td>';
  }
  html += '</tr>';
}

html = '<table>'+html+'</table>';
$body.append(html);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

注意:のjQueryためだけに使われイラストのためのコードを参照 distance 機能です。

はい、ダイクストラとBFSはあなたに答えを得るだろうが、私はこの問題のチェスのコンテキストは、特に無限のチェスボード上で、はるかに高速汎用の最短経路アルゴリズムよりも解決策を得ることができる知識を提供していと思います。

簡単にするために、の(x、y)は平面としてチェスボードを記述してみましょう。目標(+ -1、+ -2)のみ候補の手順を使用して(X1、Y1)と(X0、Y0)からの最短経路を見つけることである、(+ -2、+ -1)、及び(+ -2 、+ -2)、問題のPSに記載されるように

はここで新たな観察である:(X-4、Y + 4)、(X + 4、Y-4)、(X + 4、Y、コーナー(X-4、Y-4)で四角形を描きます4)。このセットは(S4それを呼び出す)32点を含みます。 (x、y)に、これらの32点のいずれかからの最短パスが必要ちょうど二つ移動

(x、y)にセットS3(同様に定義)で24点のいずれかからの最短経路は、の少なくとも二つの移動必要

したがって、もし| X1-X0 |> 4または| Y1-Y0 |> 4、(X1、Y1)と(X0、Y0)からの最短経路が(X0から最短経路より正確に2移動大きいです、 S4へY0)。そして、後者の問題は、単純な反復で迅速に解決することができます。

レッツN = MAX(| X1-X0 |、| Y1-Y0 |)。もしN> = 4、次いで、(X1、Y1)と(X0、Y0)から最短経路有するのはceil(N / 2)の手順

O(1)[ https://stackoverflow.com/a/8778592/4288232 のムスタファによって上記解答セルダル・シャンル]は本当に機能していません。 ((1,0)または(2,2)の明白なエッジケースの脇チェック(1,1)または(3,2)または(4,4))。

以下は、(追加「テスト」との)仕事をするくらい醜い溶液(パイソン)、次のとおりです。

def solve(x,y):
        x = abs(x)
        y = abs(y)
        if y > x:
            temp=y
            y=x
            x=temp  
        if (x==2 and y==2):
            return 4
        if (x==1 and y==0):
            return 3

    if(y == 0 or float(y) / float(x) <= 0.5):
        xClass = x % 4
        if (xClass == 0):
            initX = x/2
        elif(xClass == 1):
            initX = 1 + (x/2)
        elif(xClass == 2):
            initX = 1 + (x/2)
        else:
            initX = 1 + ((x+1)/2)

        if (xClass > 1):
            return initX - (y%2)
        else:
            return initX + (y%2)
    else:
        diagonal = x - ((x-y)/2)
        if((x-y)%2 == 0):
            if (diagonal % 3 == 0):
                return (diagonal/3)*2
            if (diagonal % 3 == 1):
                return ((diagonal/3)*2)+2
            else:
                return ((diagonal/3)*2)+2
        else:
            return ((diagonal/3)*2)+1


def test():
    real=[
    [0,3,2,3,2,3,4,5,4,5,6,7,6,7],
    [3,2,1,2,3,4,3,4,5,6,5,6,7,8],
    [2,1,4,3,2,3,4,5,4,5,6,7,6,7],
    [3,2,3,2,3,4,3,4,5,6,5,6,7,8],
    [2,3,2,3,4,3,4,5,4,5,6,7,6,7],
    [3,4,3,4,3,4,5,4,5,6,5,6,7,8],
    [4,3,4,3,4,5,4,5,6,5,6,7,6,7],
    [5,4,5,4,5,4,5,6,5,6,7,6,7,8],
    [4,5,4,5,4,5,6,5,6,7,6,7,8,7],
    [5,6,5,6,5,6,5,6,7,6,7,8,7,8],
    [6,5,6,5,6,5,6,7,6,7,8,7,8,9],
    [7,6,7,6,7,6,7,6,7,8,7,8,9,8]]

    for x in range(12):
        for y in range(12):
            res = solve(x,y)
            if res!= real[x][y]:
                print (x, y), "failed, and returned", res, "rather than", real[x][y]
            else:
               print (x, y), "worked. Cool!"

test()
何をする必要がボード上のすべての位置は、ノードやエッジなどの他の位置に移動可能である、グラフ、など騎士の可能な動きを考えています。すべてのエッジが同じ重さや距離を(彼らはすべて同じように簡単または短い行うになっている)があるため、ダイクストラ法のための必要はありません。あなたが終了位置に到達するまで、あなたは自分の開始点からBFSの検索を行うことができます。

溶液の第一原理からPython

私は最初に検出されたこの問題にCodilityます。も30分でこれを解決するために-かかったとのことを大幅に超えることにこの結果!この問題:どのように多くの動きとのことですから、またブックトークで"和菓子のアン"になっていくことになるでしょう0,0にx、yのみを使用法騎士の動します。xとyにしたまたは下限(いまいについてはこちらを簡単に8×8chessboard).

っO(1)。また、ソリューションのプログラムを明らかにしたり、問題を解決す(たいと思ったものより明らかに右上Graemeのパターン-パターンをしてい癖を破壊すい、年を取っていないに頼unargued式としてムスタファソリューション

ですから、私は、解決のために?開始、その他いかを調べることにより、ソリューションが左右対称の軸diagonalsので、その解決のみ0>=y>=x.簡単のための説明(コード)を行っている逆問題:のナイト開始を、x、y、を目指して0,0.

しようとして短縮することで問題の近くのです。またどのような"vicinty'を実際に手段によるコースではしょうがないので書ソフトウェア技術者によるcheatsheet(原点で右下)

2 1 4 3
3 2 1 2
0 3 2 3

なので、指定されたx,yのグリッドまでの読みの数に移動します。

がスタートしていますが、自分たち以外のグリッドのお仕事帰します。ご紹介の正中線、の線で表されるy=x/2になります。他のナイトx、yの位置をできるそのcheatsheet用シリーズの8時位置に移動する:(-2,-1)。の場合、x,y上にあるの正中線、その後する必要がありま次の8時の間、7時位置に移動すれば下にある、正中線を必要との連続8時、10時の方が動きます。二つのことに注意す。

  • これらの配列をprovably短います。(いうことを証明しているのか、あるいは明らかな?)
  • すみだの数をベースに行われます。までパッケージ、導波路やファイバに移動できます。

で見られるように、上記の正中線ます。私たちの主張である:

  • (dx;dy)=(2,1;1,2)(n8;n7)(マトリクス表記はなく、数学組版-列ベクトル(dx;dy)equalsクマトリクスを乗じた列ベクトル(n8;n7)の8時位置に移動し、7時位置に移動し、同様に;

  • (dx;dy)=(2,2;1,-1)(n8;n10)

いることを主張するdx,dy約(x,y)、x-dx、y dy)の周辺の起源は何で周辺'が)になります。

二つのラインのコードを計算するこれらの条項のものをこれらが、彼らが選択して有用性

  • 上記の正中線式移動(x,y)の(0,0),(1,1)、(2,2).
  • 以下の正中線式移動(x,y)の(0,0), (1,0), (2,0), 又は(1,1).

まい証明られます。) その騎士の距離れの和n7,n8,n10とcheatsheet[x-dx、y dy]、cheatsheetに減少するこ

. . 4
. 2 .
0 3 2

これなのにとどまった。の3月.唯一の方法でできることは:

  • 始めましたが、
  • 移転致しましたが、シーケンスの8時、10時の方が動きます。だが最後に移動した8時の間(こす権利を有することが出来る当社の動きを任意の順序)、そばを通過した(3,1)、距離を実際に2(これを見ていただきますと、元のcheatsheet).うにしていくべきであるバックトラック一8時の間、節約でき、移動できます。

が似最適化するた4つです。ほから始まりに到達する唯一の方法は8時から(4,3).ことになるのcheatsheetものであり、その距離が3,いて7o'clockedる(3,1)ではなく、距離の2.もしバックトラック一の8時位置に移動し、その前の7時まで。

そこで、追加する必要があり一番のcheatsheet:

. . 4
. 2 . 2
0 3 2

(注:が全体の負荷の追跡optimisationsからの(0,1)および(0,2)の解いがありませんの心配をする必要が忘れないようにしてください。

こちらでは、その後はPythonコードの評価:

def knightDistance (x, y):
    # normalise the coordinates
    x, y = abs(x), abs(y)
    if (x<y): x, y = y, x
    # now 0 <= y <= x

    # n8 means (-2,-1) (8 o'clock), n7 means (-1,-2) (7 o'clock), n10 means (-2,+1) (10 o'clock)
    if (x>2*y):
        # we're below the midline.  Using 8- & 10-o'clock moves
        n7, n8, n10 = 0,  (x + 2*y)//4,  (x - 2*y + 1)//4
    else:
        # we're above the midline.  Using 7- and 8-o'clock moves
        n7, n8, n10 = (2*y - x)//3, (2*x - y)//3,  0
    x -= 2*n8 + n7 + 2*n10
    y -= n8 + 2*n7 - n10
    # now 0<=x<=2, and y <= x.  Also (x,y) != (2,1)

    # Try to optimise the paths.
    if (x, y)==(1, 0): # hit the  3.  Did we need to?
        if (n8>0): # could have passed through the 2 at 3,1.  Back-up
            x, y = 3, 1; n8-=1;
    if (x, y)==(2, 2): # hit the 4.  Did we need to?
        if (n8>0): # could have passed through a 3 at 4,3.  Back-up, and take 7 o'clock to 2 at 3,1
            x, y = 3, 1; n8-=1; n7+=1

    # Almost there.  Now look up the final leg
    cheatsheet = [[0, 3, 2], [2, None, 2], [4]]
    return n7 + n8 + n10 + cheatsheet [y][x-y]

ちなみに、く知りたい方実際のルート、そしてこのアルゴリズムを提供するもの:とても簡単で継承n7 7-時位置に移動し、次いで(または列)n8の8時の間、n10の10時位置に移動し、どんなダンスはご覧のcheatsheetるもので、cheatsheet).

現在:どのように証明することについてはその通りである。すだけではないとの比較検討結果の一覧表を作り、右に回答では、問題自体が無制限.ができましいという場合には騎士の距離平s d、その場合は{m}は法律からsの騎士の距離(s+m)わなければいけ会大会学術講演梗概集.d-1d+1すべてのm.(いまの証明は必要。) また、与えられたテーブルを作成するようなスクエアが距離d-1なのです。この証明する正確性を示すこの物件のために保有する各広場があります。このように:

def validate (n):

    def isSquareReasonable (x, y):
        d, downhills = knightDistance (x, y), 0
        moves = [(1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1), (-2, 1), (-1,  2)]
        for dx, dy in moves:
            dd = knightDistance (x+dx,  y+dy)
            if (dd == d+1): pass
            elif (dd== d-1): downhills += 1
            else: return False;
        return (downhills>0) or (d==0)

    for x in range (0,  n+1):
        for y in range (0,  n+1):
            if not isSquareReasonable (x,  y): raise RuntimeError ("Validation failed")

また、証が正確であるかのいずれかのクエア"s追いかけの路線からs期待できる。最初に、チェック"s"のための合理性とそれを選択しs+mる距離(s+m)==会大会学術講演梗概集.d-1.まで繰り返しに達します。

Howzat?

/*
This program takes two sets of cordinates on a 8*8 chessboard, representing the
starting and ending points of a knight's path.
The problem is to print the cordinates that the knight traverses in between, following
the shortest path it can take.
Normally this program is to be implemented using the Djikstra's algorithm(using graphs)
but can also be implemented using the array method.
NOTE:Between 2 points there may be more than one shortest path. This program prints
only one of them.
*/

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

int m1=0,m2=0;

/*
This array contains three columns and 37 rows:
The rows signify the possible coordinate differences.
The columns 1 and 2 contains the possible permutations of the row and column difference 
between two positions on a chess board;
The column 3 contains the minimum number of steps involved in traversing the knight's 
path with the given permutation*/

int arr[37][3]={{0,0,0},{0,1,3},{0,2,2},{0,3,3},{0,4,2},{0,5,3},{0,6,4},{0,7,5},    {1,1,2},{1,2,1},{1,3,2},{1,4,3},{1,5,4},{1,6,3},{1,7,4},{2,2,4},{2,3,3},{2,4,2},
            {2,5,3},{2,6,3},{2,7,5},{3,3,2},{3,4,3},{3,5,4},{3,6,3},{3,7,4},{4,4,4},{4,5,3},{4,6,4},{4,7,5},{5,5,4},{5,6,5},{5,7,4},{6,6,5},{6,7,5},{7,7,6}};

void printMoves(int,int,int,int,int,int);
void futrLegalMove(int,int,int,int);
main()
{
  printf("KNIGHT'S SHORTEST PATH ON A 8*8 CHESSBOARD :\n");
  printf("------------------------------------------");
  printf("\nThe chessboard may be treated as a 8*8 array here i.e. the (1,1) ");
  printf("\non chessboard is to be referred as (0,0) here and same for (8,8) ");
  printf("\nwhich is to be referred as (7,7) and likewise.\n");
  int ix,iy,fx,fy;
  printf("\nEnter the initial position of the knight :\n");
  scanf("%d%d",&ix,&iy);
  printf("\nEnter the final position to be reached :\n");
  scanf("%d%d",&fx,&fy);
  int px=ix,py=iy;
  int temp;
  int tx,ty;
  printf("\nThe Knight's shortest path is given by :\n\n");
  printf("(%d, %d)",ix,iy);
  futrLegalMove(px,py,m1,m2);
  printMoves(px,py,fx,fy,m1,m2);
   getch();
} 

/*
  This method checkSteps() checks the minimum number of steps involved from current
  position(a & b) to final position(c & d) by looking up in the array arr[][].
*/

int checkSteps(int a,int b,int c,int d)
{  
    int xdiff, ydiff;
    int i, j;
    if(c>a)
        xdiff=c-a;
    else
        xdiff=a-c;
    if(d>b)
        ydiff=d-b;
    else
        ydiff=b-d;
    for(i=0;i<37;i++)
        {
            if(((xdiff==arr[i][0])&&(ydiff==arr[i][1])) || ((xdiff==arr[i][1])&& (ydiff==arr[i] [0])))
            {
                j=arr[i][2];break;
            }
        }

        return j;
}   

/*
This method printMoves() prints all the moves involved.
*/

void printMoves(int px,int py, int fx, int fy,int a,int b)
{    
 int temp;
 int tx,ty;
 int t1,t2;
  while(!((px==fx) && (py==fy)))
  {   
      printf(" --> ");
      temp=checkSteps(px+a,py+b,fx,fy);
      tx=px+a;
      ty=py+b;
      if(!(a==2 && b==1))
      {if((checkSteps(px+2,py+1,fx,fy)<temp) && checkMove(px+2,py+1))
      {temp=checkSteps(px+2,py+1,fx,fy);
       tx=px+2;ty=py+1;}}
      if(!(a==2 && b==-1))
      {if((checkSteps(px+2,py-1,fx,fy)<temp) && checkMove(px+2,py-1))
      {temp=checkSteps(px+2,py-1,fx,fy);
       tx=px+2;ty=py-1;}}
      if(!(a==-2 && b==1))
      {if((checkSteps(px-2,py+1,fx,fy)<temp) && checkMove(px-2,py+1))
      {temp=checkSteps(px-2,py+1,fx,fy);
       tx=px-2;ty=py+1;}}
      if(!(a==-2 && b==-1))
      {if((checkSteps(px-2,py-1,fx,fy)<temp) && checkMove(px-2,py-1))
      {temp=checkSteps(px-2,py-1,fx,fy);
       tx=px-2;ty=py-1;}}
      if(!(a==1 && b==2))
      {if((checkSteps(px+1,py+2,fx,fy)<temp) && checkMove(px+1,py+2))
      {temp=checkSteps(px+1,py+2,fx,fy);
       tx=px+1;ty=py+2;}}
      if(!(a==1 && b==-2))
      {if((checkSteps(px+1,py-2,fx,fy)<temp) && checkMove(px+1,py-2))
      {temp=checkSteps(px+1,py-2,fx,fy);
       tx=px+1;ty=py-2;}}
      if(!(a==-1 && b==2))
      {if((checkSteps(px-1,py+2,fx,fy)<temp) && checkMove(px-1,py+2))
      {temp=checkSteps(px-1,py+2,fx,fy);
       tx=px-1;ty=py+2;}}
      if(!(a==-1 && b==-2))
      {if((checkSteps(px-1,py-2,fx,fy)<temp) && checkMove(px-1,py-2))
      {temp=checkSteps(px-1,py-2,fx,fy);
       tx=px-1;ty=py-2;}}
       t1=tx-px;//the step taken in the current move in the x direction.
       t2=ty-py;//" " " " " " " " " " " " " " " " " " " " " y " " " " ".
       px=tx;
       py=ty;
       printf("(%d, %d)",px,py);
       futrLegalMove(px,py,t1,t2);
       a=m1;
       b=m2;
   }

} 

/*
The method checkMove() checks whether the move in consideration is beyond the scope of
board or not.
*/   

int checkMove(int a, int b)
{
    if(a>7 || b>7 || a<0 || b<0)
        return 0;
    else
        return 1;
}

/*Out of the 8 possible moves, this function futrLegalMove() sets the valid move by
  applying the following constraints
      1. The next move should not be beyond the scope of the board.
      2. The next move should not be the exact opposite of the previous move.
  The 1st constraint is checked by sending all possible moves to the checkMove() 
  method;
  The 2nd constraint is checked by passing as parameters(i.e. a and b) the steps of the 
  previous move and checking whether or not it is the exact opposite of the current move.
*/

void futrLegalMove(int px,int py,int a,int b)
{
     if(checkMove(px+2,py+1) && (a!=-2 && b!=-1))
         m1=2,m2=1;
     else
     {
         if(checkMove(px+2,py-1)&& (a!=-2 && b!=1))
             m1=2,m2=-1;
     else
     {
         if(checkMove(px-2,py+1)&& (a!=2 && b!=-1))
              m1=-2,m2=1;
     else
     {
         if(checkMove(px-2,py-1)&& (a!=2 && b!=1))
               m1=-2,m2=-1;
     else
     {
         if(checkMove(px+1,py+2)&& (b!=-2 && a!=-1))
               m2=2,m1=1;
     else
     {
         if(checkMove(px+1,py-2)&& (a!=-1 && b!=2))
               m2=-2,m1=1;
     else
     {
         if(checkMove(px-1,py+2)&& (a!=1 && b!=-2))
               m2=2,m1=-1;
     else
     {
         if(checkMove(px-1,py-2)&& (a!=1 && b!=2))
               m2=-2,m1=-1;
     }}}}}}}
}

//End of Program.
私は単に配列を通してそれを実現するための問題ごとにグラフyet..asを研究していないが、私はこれ以外の解決策を導き出すことができませんでした。私はないランクとファイル(通常のチェス表記)としてではなく、配列のインデックスとして位置を処理しました。 FYI、これが唯一の8 * 8のチェス盤のためです。任意の改善アドバイスは常に歓迎されます。

*コメントは、ロジックのご理解のために十分です。しかし、あなたが常に求められることがあります。

* DEV-C ++コンパイラ4.9.9.2(流血ソフトウェア)にチェックます。

私は、これはまた、あなた..

を助けるかもしれないことを考えます
NumWays(x,y)=1+min(NumWays(x+-2,y-+1),NumWays(x+-1,y+-2)); 

と解決策を得るために、動的プログラミングを使用します。

P.S:それはちょっとグラフのノードおよびエッジを宣言する手間を取ることなく、BFSを使用する

ここではPerlで実装され、この特定の問題のためのソリューションです。いくつかのケースでは、複数のがあるかもしれません。

- これは、最短経路のいずれかが表示されます。

私は使用しませんでしたアルゴリズムのいずれかが、上記の - 。しかし、他のソリューションと比較するとよいでしょう。

#!/usr/local/bin/perl -w

use strict;

my $from = [0,0];
my $to   = [7,7];

my $f_from = flat($from);
my $f_to   = flat($to);

my $max_x = 7;
my $max_y = 7;
my @moves = ([-1,2],[1,2],[2,1],[2,-1],[1,-2],[-1,-2],[-2,-1],[-2,1]);
my %squares = ();
my $i = 0;
my $min = -1;

my @s = ( $from );

while ( @s ) {

   my @n = ();
   $i++;

   foreach my $s ( @s ) {
       unless ( $squares{ flat($s) } ) {
            my @m = moves( $s );
            push @n, @m;
            $squares{ flat($s) } = { i=>$i, n=>{ map {flat($_)=>1} @m }, };

            $min = $i if $squares{ flat($s) }->{n}->{$f_to};
       }
   }

   last if $min > -1;
   @s = @n;
}

show_path( $f_to, $min );

sub show_path {
    my ($s,$i) = @_;

    return if $s eq $f_from;

    print "$i => $f_to\n" if $i == $min;

    foreach my $k ( keys %squares ) {
       if ( $squares{$k}->{i} == $i && $squares{$k}->{n}->{$s} ) {
            $i--;
            print "$i => $k\n";
            show_path( $k, $i );
            last;
       }
    }
}

sub flat { "$_[0]->[0],$_[0]->[1]" }

sub moves {
    my $c = shift;
    my @s = ();

    foreach my $m ( @moves ) {
       my $x = $c->[0] + $m->[0];
       my $y = $c->[1] + $m->[1];

       if ( $x >= 0 && $x <=$max_x && $y >=0 && $y <=$max_y) {
           push @s, [$x, $y];
       }
    }
    return @s;
}

__END__
public class Horse {

    private int[][] board;
    private int[] xer = { 2, 1, -1, -2, -2, -1, 1, 2 };
    private int[] yer = { 1, 2, 2, 1, -1, -2, -2, -1 };
    private final static int A_BIG_NUMBER = 10000;
    private final static int UPPER_BOUND = 64;


    public Horse() {
        board =  new int[8][8];
    }

    private int solution(int x, int y, int destx, int desty, int move) {

        if(move == UPPER_BOUND) {
            /* lets put an upper bound to avoid stack overflow */
            return A_BIG_NUMBER;
        }

        if(x == 6 && y ==5) {
            board[6][5] = 1;
            return 1;
        }
        int min = A_BIG_NUMBER;
        for (int i = 0 ; i < xer.length; i++) {
            if (isMoveGood(x + xer[i], y + yer[i])) {
                if(board[x + xer[i]][y + yer[i]] != 0) {
                    min = Integer.min(min, 1 + board[x +xer[i]] [y +yer[i]]);                   
                } else {
                    min = Integer.min(min, 1 + solution(x + xer[i], y + yer[i], destx, desty, move + 1));   
                }                   
            }
        }   
        board[x][y] = min;
        return min;
    }


    private boolean isMoveGood(int x, int y) {
        if (x >= 0 && x < board.length && y >= 0 && y < board.length)
            return true;
        return false;
    }


    public static void main(String[] args) {

        int destX = 6;
        int destY = 7;
        final Horse h = new Horse();
        System.out.println(h.solution(0, 0, destX, destY, 0));
    }
}

の上記グレアム・パイルの答えのjsfiddleからわずかRubyのコードは、すべての余分なコードをストライピングだけ解を得るためにルビーために、残りの変換しました彼のアルゴリズムにより、作業のように思えます。それでもかかわらず、テストます:

def getBoardOffset(board)
  return board.length / 2
end

def setMoveCount(x, y, count, board)
  offset = getBoardOffset(board)
  board[y + offset][x + offset] = count
end

def getMoveCount(x, y, board)
    offset = getBoardOffset(board)
    row = board[y + offset]
    return row[x + offset]
end

def isBottomOfVerticalCase(x, y)
    return (y - 2 * x) % 4 == 0
end

def isPrimaryDiagonalCase(x, y)
    return (x + y) % 2 == 0
end

def isSecondaryDiagonalCase(x, y)
    return (x + y) % 2 == 1
end

def simplifyBySymmetry(x, y)
    x = x.abs
    y = y.abs
    if (y < x)
      t = x
      x = y
      y = t
    end
    return {x: x, y: y}
end

def getPrimaryDiagonalCaseMoveCount(x, y)
    var diagonalOffset = y + x
    var diagonalIntersect = diagonalOffset / 2
    return ((diagonalIntersect + 2) / 3).floor * 2
end

def getSpecialCaseMoveCount(x, y)
    specials = [{
            x: 0,
            y: 0,
            d: 0
        },
        {
            x: 0,
            y: 1,
            d: 3
        },
        {
            x: 0,
            y: 2,
            d: 2
        },
        {
            x: 0,
            y: 3,
            d: 3
        },
        {
            x: 2,
            y: 2,
            d: 4
        },
        {
            x: 1,
            y: 1,
            d: 2
        },
        {
            x: 3,
            y: 3,
            d: 2
        }
    ];
    matchingSpecial=nil
    specials.each do |special|
      if (special[:x] == x && special[:y] == y)
        matchingSpecial = special
      end
    end
    if (matchingSpecial)
      return matchingSpecial[:d]
    end
end

def isVerticalCase(x, y)
  return y >= 2 * x
end

def getVerticalCaseMoveCount(x, y)
    normalizedHeight = getNormalizedHeightForVerticalGroupCase(x, y)
    groupIndex = (normalizedHeight/4).floor
    groupStartMoveCount = groupIndex * 2 + x
    return groupStartMoveCount + getIndexInVerticalGroup(x, y)
end

def getIndexInVerticalGroup(x, y)
    return getNormalizedHeightForVerticalGroupCase(x, y) % 4
end

def getYOffsetForVerticalGroupCase(x) 
    return x * 2
end

def getNormalizedHeightForVerticalGroupCase(x, y)
    return y - getYOffsetForVerticalGroupCase(x)
end

def getSecondaryDiagonalCaseMoveCount(x, y)
    diagonalOffset = y + x
    diagonalIntersect = diagonalOffset / 2 - 1
    return ((diagonalIntersect + 2) / 3).floor * 2 + 1
end

def getMoveCountO1(x, y)
    newXY = simplifyBySymmetry(x, y)
    x = newXY[:x]
    y = newXY[:y]
    specialMoveCount = getSpecialCaseMoveCount(x ,y)
    if (specialMoveCount != nil)
      return specialMoveCount
    elsif (isVerticalCase(x, y))
      return getVerticalCaseMoveCount(x ,y)
    elsif (isPrimaryDiagonalCase(x, y))
      return getPrimaryDiagonalCaseMoveCount(x ,y)
    elsif (isSecondaryDiagonalCase(x, y))
      return getSecondaryDiagonalCaseMoveCount(x ,y)
    end
end

def solution(x ,y)
  return getMoveCountO1(x, y)
end


puts solution(0,0)

のみ意図誰もが完全なコードが必要な場合は、コードを変換し、誰かにいくつかの時間を節約することです。

ここジュール月の機能のPHPのバージョンがあります。

function knightDistance($x, $y)
{
    $x = abs($x);
    $y = abs($y);

    if($x < $y)
    {
        $tmp = $x;
        $x = $y;
        $y = $tmp;
    }

    if($x > 2 * $y)
    {
        $n7 = 0;
        $n8 = floor(($x + 2*$y) / 4);
        $n10 = floor(($x - 2*$y +1) / 4);
    }
    else
    {
        $n7 = floor((2*$y - $x) / 3);
        $n8 = floor((2*$x - $y) / 3);
        $n10 = 0;
    }

    $x -= 2 * $n8 + $n7 + 2 * $n10;
    $y -= $n8 + 2 * $n7 - $n10;

    if($x == 1 && $y == 0)
    {
        if($n8 > 0)
        {
            $x = 3;
            $y = 1;
            $n8--;
        }
    }
    if($x == 2 && $y == 2)
    {
        if($n8 > 0)
        {
            $x = 3;
            $y = 1;
            $n8--;
            $n7++;
        }
    }

    $cheatsheet = [[0, 3, 2], [2, 0, 2], [4]];

    return $n7 + $n8 + $n10 + $cheatsheet [$y][$x-$y];
}

ここに私のプログラムです。 これは完璧なソリューションではありません。再帰関数で作る変更がたくさんあります。しかし、この最終結果は完璧です。 Iビットを最適化しようとした。

public class KnightKing2 {
    private static int tempCount = 0;

    public static void main(String[] args) throws IOException {
        Scanner in = new Scanner(System.in);
        int ip1 = Integer.parseInt(in.nextLine().trim());
        int ip2 = Integer.parseInt(in.nextLine().trim());
        int ip3 = Integer.parseInt(in.nextLine().trim());
        int ip4 = Integer.parseInt(in.nextLine().trim());
        in.close();
        int output = getStepCount(ip1, ip2, ip3, ip4);
        System.out.println("Shortest Path :" + tempCount);

    }

    // 2 1 6 5 -> 4
    // 6 6 5 5 -> 2

    public static int getStepCount(int input1, int input2, int input3, int input4) {
        return recurse(0, input1, input2, input3, input4);

    }

    private static int recurse(int count, int tx, int ty, int kx, int ky) {

        if (isSolved(tx, ty, kx, ky)) {
            int ccount = count+1;
            System.out.println("COUNT: "+count+"--"+tx+","+ty+","+ccount);
            if((tempCount==0) || (ccount<=tempCount)){
                tempCount = ccount;
            }
            return ccount;
        }

            if ((tempCount==0 || count < tempCount) && ((tx < kx+2) && (ty < ky+2))) {
                if (!(tx + 2 > 8) && !(ty + 1 > 8)) {
                    rightTop(count, tx, ty, kx, ky);

                }
                if (!(tx + 2 > 8) && !(ty - 1 < 0)) {
                    rightBottom(count, tx, ty, kx, ky);
                }
                if (!(tx + 1 > 8) && !(ty + 2 > 8)) {
                    topRight(count, tx, ty, kx, ky);
                }
                if (!(tx - 1 < 0) && !(ty + 2 > 8)) {
                    topLeft(count, tx, ty, kx, ky);
                }
                if (!(tx + 1 > 8) && !(ty - 2 < 0)) {
                     bottomRight(count, tx, ty, kx, ky);
                }
                if (!(tx - 1 < 0) && !(ty - 2 < 0)) {
                     bottomLeft(count, tx, ty, kx, ky);
                }
                if (!(tx - 2 < 0) && !(ty + 1 > 8)) {
                    leftTop(count, tx, ty, kx, ky);
                }
                if (!(tx - 2 < 0) && !(ty - 1 < 0)) {
                    leftBottom(count, tx, ty, kx, ky);
                }
            }

        return count;

    }

    private static int rightTop(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx + 2, ty + 1, kx, ky);

    }

    private static int topRight(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx + 1, ty + 2, kx, ky);
    }

    private static int rightBottom(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx + 2, ty - 1, kx, ky);
    }

    private static int bottomRight(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx + 1, ty - 2, kx, ky);
    }

    private static int topLeft(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx - 1, ty + 2, kx, ky);
    }

    private static int bottomLeft(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx - 1, ty - 2, kx, ky);
    }

    private static int leftTop(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx - 2, ty + 1, kx, ky);
    }

    private static int leftBottom(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx - 2, ty - 1, kx, ky);
    }

    private static boolean isSolved(int tx, int ty, int kx, int ky) {
        boolean solved = false;
        if ((tx == kx) && (ty == ky)) {
            solved = true;
        } else if ((tx + 2 == kx) && (ty + 1 == ky)) { // right top
            solved = true;
        } else if ((tx + 2 == kx) && (ty - 1 == ky)) { // right bottom
            solved = true;
        } else if ((ty + 2 == ky) && (tx + 1 == kx)) {// top right
            solved = true;
        } else if ((ty + 2 == ky) && (tx - 1 == kx)) {// top left
            solved = true;
        } else if ((tx - 2 == kx) && (ty + 1 == ky)) { // left top
            solved = true;
        } else if ((tx - 2 == kx) && (ty - 1 == ky)) {// left bottom
            solved = true;
        } else if ((ty - 2 == ky) && (tx + 1 == kx)) { // bottom right
            solved = true;
        } else if ((ty - 2 == ky) && (tx - 1 == kx)) { // bottom left
            solved = true;
        }

        return solved;
    }

}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top