paizaキャンペーン問題「怪盗813からの挑戦状」を解いてみた
問題を解いたら、抽選でAmazonギフト券とかお肉とかが貰えるとのことで、チャレンジしてみた。
https://paiza.jp/poh/phantom_thief
問題
お宝の場所の情報は怪盗の居る場所を 0, 0 として N 個 のお宝の x, y 座標がメートル単位で書かれています。
各座標間は直線で移動します。0, 0 の位置からスタートし、可能な限り短いルートでお宝を全て盗むルートを出力してください。
考え方
原点から一番近い座標を出力して、その座標からまた一番近い座標を出力して…を繰り返せば、短いルートで進めるのでは?と思って、解いてみた。
解答をブログとかに書いてもいいと書いてあったので、以下に掲載。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String firstLine = sc.nextLine().replaceAll(" ","");
int itemCount = Integer.parseInt(firstLine);
ArrayList<Point> pointList = new ArrayList<Point>();
//標準入力から座標リストを作成する
for(int i = 0; i < itemCount ; i++){
String[] line = sc.nextLine().split(" ");
int x = Integer.parseInt(line[0]);
int y = Integer.parseInt(line[1]);
pointList.add(new Point(x,y));
}
Point originPoint = new Point(0,0);
while(pointList.size() > 0){
int minDistance = Integer.MAX_VALUE;
Point minDistancePoint = new Point();
//基準点から一番距離の近い座標を座標リストから取得する
for(Point getPoint : pointList){
int tmpDistance = getDistance(originPoint,getPoint);
if(minDistance > tmpDistance){
minDistance = tmpDistance;
minDistancePoint = getPoint;
}
}
//座標位置を表示する
minDistancePoint.output();
//基準点を変更する
originPoint = minDistancePoint;
//座標リストから座標を削除する
int index = pointList.indexOf(minDistancePoint);
pointList.remove(index);
}
}
//二点の座標間の距離を求める
public static int getDistance(Point p1, Point p2) {
double x1 = p1.x;
double y1 = p1.y;
double x2 = p2.x;
double y2 = p2.y;
double distance = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
return (int) distance;
}
}
//座標クラス
class Point{
int x;
int y;
public Point(){
this.x = 0;
this.y = 0;
}
public Point(int x , int y){
this.x = x;
this.y = y;
}
public void output(){
System.out.println(x + " " + y);
}
}
結果
こちら。最適解じゃなかったようだ。
https://paiza.jp/poh/phantom_thief/result/a8a222d8
最適解を求めるには?
ちょっと調べたところ、巡回セールスマン問題と呼ばれる問題っぽい。
(最初の座標に戻らなくていいので、少し違う?)
今回私が解いた方法は「欲張り法」というアルゴリズムのようだ。
巡回セールスマン問題を解くためのアルゴリズムには「2-opt法」「山登り法」「焼きなまし法」などがあり、これらを使うともっと最適解に近くなるようだけど、難しそうなので諦めた。
Author And Source
この問題について(paizaキャンペーン問題「怪盗813からの挑戦状」を解いてみた), 我々は、より多くの情報をここで見つけました https://qiita.com/suttoko0815/items/d1fb7610ef9cd54e63d2著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .