🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

1回答

1710閲覧

【アルゴリズム】格子点の問題

Sh1xy0u

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2021/02/10 05:13

前提・実現したいこと

ロジック力強化のためにアルゴリズムの勉強をしているのですが、
以下の問題のアルゴリズムをどうすればよいかわかりません。

問題文

あなたは現在 xy 平面上の格子点 (X1,Y1) にいます。 あなたは、格子点 (X2,Y2) に到達したいです。 あなたは、以下のような移動を行うことができます。 ・今いる点の x 座標が偶数のとき、 y 軸の正の方向に移動する。 ・今いる点の x 座標が奇数のとき、 y 軸の負の方向に移動する。 ・今いる点の y 座標が偶数のとき、 x 軸の正の方向に移動する。 ・今いる点の y 座標が奇数のとき、 x 軸の負の方向に移動する。 これらの移動を繰り返すことで格子点 (X2,Y2) に到達するために必要な総移動距離の最小値を求めてください。

自分の書いたソースコード

以下、現状のソースコードになります。
到達目標座標の偶奇が考慮できていないため、無限ループに入ってしまいます。

Java

1import java.util.*; 2 3public class Main { 4 5 /* 移動距離カウント用 */ 6 static int c = 0; 7 8 public static void main(String[] args) { 9 Scanner sc = new Scanner(System.in); 10 11 /* 今いる座標 */ 12 int x = sc.nextInt(); 13 int y = sc.nextInt(); 14 15 /* 到達目標座標 */ 16 final int x2 = sc.nextInt(); 17 final int y2 = sc.nextInt(); 18 19 int xyc; 20 int yxc; 21 22 int x1 = x; 23 int y1 = y; 24 25 /* y→xの順 */ 26 while (true) { 27 if (x1 % 2 == 0) { /* 今いるx座標が偶数 */ 28 y1 += moveCoordinate(y1, y2, "even"); 29 } else if (Math.abs(x1 % 2) == 1) { /* 今いるx座標が奇数 */ 30 y1 += moveCoordinate(y1, y2, "odd"); 31 } 32 33 System.out.println(x1 + " " + y1); 34 35 if (x1 == x2 && y1 == y2) { 36 break; 37 } 38 39 if (y1 % 2 == 0) { /* 今いるy座標が偶数 */ 40 x1 += moveCoordinate(x1, x2, "even"); 41 } else if (Math.abs(y1 % 2) == 1) { /* 今いるy座標が奇数 */ 42 x1 += moveCoordinate(x1, x2, "odd"); 43 } 44 45 System.out.println(x1 + " " + y1); 46 47 if (x1 == x2 && y1 == y2) { 48 break; 49 } 50 } 51 //System.out.println(c); 52 yxc = c; 53 54 c = 0; 55 x1 = x; 56 y1 = y; 57 58 System.out.println(); 59 /* x→yの順 */ 60 while (true) { 61 if (y1 % 2 == 0) { /* 今いるy座標が偶数 */ 62 x1 += moveCoordinate(x1, x2, "even"); 63 } else if (Math.abs(y1 % 2) == 1) { /* 今いるy座標が奇数 */ 64 x1 += moveCoordinate(x1, x2, "odd"); 65 } 66 67 System.out.println(x1 + " " + y1); 68 69 if (x1 == x2 && y1 == y2) { 70 break; 71 } 72 73 if (x1 % 2 == 0) { /* 今いるx座標が偶数 */ 74 y1 += moveCoordinate(y1, y2, "even"); 75 } else if (Math.abs(x1 % 2) == 1) { /* 今いるx座標が奇数 */ 76 y1 += moveCoordinate(y1, y2, "odd"); 77 } 78 79 System.out.println(x1 + " " + y1); 80 81 if (x1 == x2 && y1 == y2) { 82 break; 83 } 84 } 85 //System.out.println(c); 86 xyc = c; 87 88 if (xyc < yxc) { /* x軸→y軸の順 */ 89 System.out.println(xyc); 90 } else { /* y軸→x軸の順 */ 91 System.out.println(yxc); 92 } 93 94 } 95 96 public static int moveCoordinate(int a, int b, String evenness) { 97 if (evenness == "even") { // 正方向へ移動 98 if (a < b) { 99 c += Math.abs(b - a); 100 return Math.abs(b - a); 101 } else /* if (a >= b) */{ 102 c++; 103 return 1; 104 105 } 106 107 } else if (evenness == "odd") { // 負方向へ移動 108 if (a > b) { 109 c += Math.abs(a - b); 110 return -(Math.abs(a - b)); 111 } else /* if (a <= b) */{ 112 c++; 113 return -1; 114 } 115 } 116 return 0; 117 } 118} 119

補足情報

入力は以下の形式で標準入力から与えられる。

X1 Y1 X2 Y2

入力例1

0 1 5 1

出力例1

7

(0,1) → (0,2) → (5,2) → (5,1) と移動すると総移動距離は 7 となり、これは最小です。

入力例2

100000000 100000000 -100000000 -100000000

出力例2

400000004

(100000000,100000000) → (100000001,100000000) → (100000001,−100000001) → (−100000000,−100000001) → (−100000000,−100000000) と移動すると総移動距離は 400000004 となり、これは最小です。

入力例3

3 -1 4 8

出力例3

12

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Sh1xy0u

2021/02/10 06:03

同じですが、考え方を聞いているのではありません。 上記コードにどういう処理が足せばいいのかを質問させていただいております。
fana

2021/02/10 07:13

リンク先の回答内に > 到達目標座標の偶奇が考慮できていないため に対して,偶奇を考慮するならこういう処理かな,という話が書いてあるつもりなのですが,これでは「どういう処理を足せばいいか」という話には該当しませんか? 欲しいのは 処理の内容の話 なのではなくて,あなたのコードを土台にして完成させた具体的なコード である,という話ですか?
fana

2021/02/10 07:34

あなたの現状態に基づいての話を希望するのであれば,現状の説明をした方が良いのではないでしょうか. あなたが考えたアルゴリズムはどういうもので,現コードのどの部分がそのアルゴリズムのどこに対応してるのか,等.
guest

回答1

0

とりあえず,「質問への追記・修正の依頼」欄で示した
https://teratail.com/questions/306606#reply-430054
にある回答内容のアイデアの実装を示す.
(言語はC++になっているが,疑似コードとして読めるだろう)

XDir_then_YDirとはXとYを逆順に扱わねばならないパターンがあり得るのかどうかは不明.
(とりあえず質問文に提示されている3つの例については正答が得られているが,果たして?)
必要ならば,逆順の処理も行って,2つのうち小さい側を答えとすればよい.

C++

1//引数が偶数のとき1, 奇数のとき-1を返す 2inline int MovableDir( int P ){ return ( (P & 0x1) ? -1 : 1 ); } 3 4// 5unsigned int XDir_then_YDir( int X1,int Y1, int X2,int Y2 ) 6{ 7 unsigned int Count = 0; 8 9 int dx = X2 - X1; 10 if( dx != 0 ) 11 {//現在位置から,行きたいX方向にいけるのかを調べる. 12 //無理な場合は,行きたいX方向にいけるようにするために,まずY方向に一歩動く. 13 if( MovableDir(Y1) * dx < 0 ) 14 { Y1 += MovableDir(X1); Count=1; } 15 } 16 17 //X方向に関して,ダイレクトにX=X2に移動してよいのかどうか調べる. 18 int dy = Y2 - Y1; 19 if( MovableDir(X2) * dy >= 0 ) 20 {//X=X2から直接Y=Y2に向かえる場合 21 //X=X2に移動し,あとはY=Y2にそのまま移動すればよい. 22 return Count + abs(dx) + abs(dy); 23 } 24 else 25 {//ダイレクトにX2に移動しても所望のY方向に移動できない場合 26 //まず,X方向に関して,現在値から見て,X2の一歩手前か,あるいは一歩先まで移動する 27 //そうすれば,Y = Y2 まで移動できる. 28 //この時点で,ゴールは隣接しているから,X方向に一歩動けばいい. 29 Count += abs(dx) + abs(dy); 30 if( MovableDir(Y2) * dx < 0 ){ Count += 2; } 31 return Count; 32 } 33} 34 35int main(void) 36{ 37 std::cout << XDir_then_YDir( 0,1, 5,1 ) << std::endl; 38 std::cout << XDir_then_YDir( 100000000,100000000, -100000000,-100000000 ) << std::endl; 39 std::cout << XDir_then_YDir( 3,-1, 4,8 ) << std::endl; 40 return 0; 41}

投稿2021/02/12 10:17

編集2021/02/12 10:18
fana

総合スコア11985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2021/02/12 10:23

※ XDir_then_YDirの中身はもっと短くまとめることはできるだろうが,ここでは説明が目的なので,愚直な形の実装を示した.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問