• 締切済み

巡回セールスマン問題

巡回セールスマン問題をJavaで解きたいのですが、Nearest Neighbor法で初期解を求めるまではできたのですが、その後2-opt法を用いて再計算する段階がうまくいきません。(実行できるのですが、どのような都市配置でも経路変更されません。)  できれば理由とコードを教えてください。 文字数の関係で2-optによる再計算の部分だけソースコードの載せさせていただきます。 補足:クラスは1つです。    wayに現段階の巡回路(都市番号)が格納されています public ArrayList<Integer> revision(ArrayList<Integer> way){ for (int i = 1; i < way.size(); i++){ int a = way.get(i - 1); int b = way.get(i); for(int j = i+2; j < way.size(); j++){ int c = way.get(j - 1); int d = way.get(j); float before = distance[a][b] + distance[c][d]; float after = distance[a][c] + distance[b][d]; if ( after < before){ ArrayList<Integer> route = new ArrayList<Integer>(); for(int k = 0; k < i; k++){ route.add(way.get(k)); } for(int k = j - 1; k >= i; k--){ route.add(way.get(k)); } for(int k=j; k < way.size(); k++){ route.add(way.get(k)); } //revision(route); } } } System.out.println("更新後way = "+ way); return way; }

  • Java
  • 回答数1
  • ありがとう数0

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

way は変更しなくていいの?

関連するQ&A

  • 巡回セールスマン問題

    このプログラミングを実際に視覚的(探索している状況など)に表したいんですが、どのようにすべきなのでしょうか? いろいろ参考書を見たのですが、わかりませんでした。 import java.io.*; public class TSP { public static void main(String[] args) { TSP instance = new TSP(); TspPoint[] points = new TspPoint[5]; //コンポーネントの作成 points[0] = new TspPoint("A", 5, 10); points[1] = new TspPoint("B", 4, 2); points[2] = new TspPoint("C", 6, 3); points[3] = new TspPoint("D", 3, 4); points[4] = new TspPoint("E", 2, 7); instance.setPoints(points); instance.traveling(); instance.dispResult(); } private TspPoint[] points; private double min_distance; private int[] min_route; public void setPoints(TspPoint[] points) { this.points = points; } public void traveling() { min_distance = Double.MAX_VALUE; min_route = new int[points.length]; int p1, p2, p3, p4, p5; p1 = 0; for (p2 = 1; p2 < 5; p2++) { for (p3 = 1; p3 < 5; p3++) { for (p4 = 1; p4 < 5; p4++) { for (p5 = 1; p5 < 5; p5++) { if (p1 == p2 || p1 == p3 || p1 == p4 || p1 == p5 || p2 == p3 || p2 == p4 || p2 == p5 || p3 == p4 || p3 == p5 || p4 == p5) { // 重複する地点は対象外 } else { // p1→p2→p3→p4→p5→p1への巡回経路長を求める double distance = 0.0; distance += calcDistance(points[p1], points[p2]); distance += calcDistance(points[p2], points[p3]); distance += calcDistance(points[p3], points[p4]); distance += calcDistance(points[p4], points[p5]); distance += calcDistance(points[p5], points[p1]); if (distance < min_distance) { // 現在のところの最短経路を覚えておく min_route[0] = p1; min_route[1] = p2; min_route[2] = p3; min_route[3] = p4; min_route[4] = p5; // 最短距離を記憶する min_distance = distance; } } } } } } } public void dispResult() { System.out.print("最小の巡回経路は "); for (int i = 0; i < 5; i++) { System.out.print(points[min_route[i]].toString() + " → "); } System.out.println(points[min_route[0]].toString()); System.out.println("巡回経路長は " + min_distance); } public double calcDistance(TspPoint a, TspPoint b) { double temp; temp = (a.getX() - b.getX()) * (a.getX() - b.getX()) + (a.getY() - b.getY()) * (a.getY() - b.getY()); return Math.sqrt(temp); //平方根を返す } } class TspPoint { private String name; private int x; private int y; public TspPoint(String name, int x, int y) { this.name = name; this.x = x; this.y = y; } public String getName() { return name; } public int getX() { return x; } public int getY() { return y; } public String toString() { return name + "(" + x + "," + y + ")"; } }

  • 巡回セールスマン問題

    巡回セールスマン問題の解を求めるプログラムを作ったのですが、これでは全ての回路が表示されてしまいます。最小値だけでしかも順列の最初の値が0の回路だけを表示させるにはどうすればいいのでしょうか?どなたか教えてください。長くてすいません。 #include<stdio.h> #define MAXN (100) #define YES (1) #define NO (0) void perm(int d); int n, a[MAXN], used[MAXN]; int dist[MAXN][MAXN]; int main(void) { int i; int j; // printf("Input n: "); scanf("%d", &n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { scanf("%d", &dist[i][j]); } } if (n > MAXN) { printf("Change the value MAXN.\n"); exit(1); } else if (n < 0) { printf("Error!(Input nonnegative integer.)\n"); exit(1); } for (i = 0; i < n; i++) used[i] = NO; /* 始めはどの値も使っていない */ perm(0); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { printf("%2d ", dist[i][j]); } printf("\n"); } } /* 深さdの節点を根とする木を作成する関数 */ void perm(int d) { int i; if (d == n) { for(i = 0; i < n; i++) printf("%d", a[i]); printf("\n"); } else { for (i = 0; i < n; i++) { if (used[i] == NO) { a[d] = i; /* 配列のd番目にiを代入する */ used[i] = YES; /* iを使ったことを記憶する */ perm(d + 1); /* 再帰呼び出し */ used[i] = NO; /* 命令文を追加する */ } } } }

  • 困ってます。巡回セールスマン問題

    ネットを参考にしてゼミの課題のプログラムを書いてみたのですが、動きません。prevがあいまいです。と出ます。どうやれば動きますか?教えてください。 #include <iostream> #include <cmath> using namespace std; const int MAX_N = 20; int n; double dist[MAX_N][MAX_N]; int prev[MAX_N]; double optval = 99999.99999; int optsol[MAX_N]; void solve(int u = 0) { bool end = true; for (int v = 0; v < n; ++v) { if (prev[v] == -1) { end = false; prev[v] = u; solve(v); prev[v] = -1; } } if (end) { double length = dist[u][0]; for (int v = u; v != 0; v = prev[v]) length += dist[prev[v]][v]; if (length < optval) { optval = length; for (int i = 0; i < n; ++i) optsol[i] = prev[i]; optsol[0] = u; } } } int main() { // get input cin >> n; for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) cin >> dist[i][j]; for (int i = 0; i < n; ++i) prev[i] = -1; prev[0] = 0; solve(); for (int u = optsol[0]; u != 0; u = optsol[u]) cout << u+1 << " <- "; cout << 1 << " : " << optval << endl; }

  • プログラミング学習paizaの数の並び替え問題

    Eclipseでは上手く並び替え表示されるのですが、paizaで同じコードを提出しても、提出前動作確認でコード実行結果がWrong Anserでエラーになります。原因が分かりません。使用言語はJavaです。 import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; public class Main { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = br.readLine(); ArrayList<Integer> n_ = new ArrayList<>(); n_.add(null); while (line != null) { if (line.equals("")) { for (int a = 1; a< n_.size()-1; a++) { for (int j = a + 1; j < n_.size(); j++) { if (n_.get(a) > n_.get(j)) { int w = n_.get(a); n_.set(a, n_.get(j)); n_.set(j, w); } } } for (int k = 1; k < n_.size(); k++) { System.out.println(n_.get(k)); } break; }else{ int i = Integer.parseInt(line); n_.add(i); line = br.readLine(); } } } }

  • 総称型ArrayList<E>への参照はパラメ-タ

    Java初心者です宜しくお願いします。 0から8までの数字をランダムに並べ替えるサブ関数を作成しました。 Eclipse上で単独のプログラムとして動かした場合には、エラーは出ませんが、他のプログラムの サブ関数として動かそうとすると、 「ArrayListはraw型です。 総称型ArrayList<E>への参照は、パラメ-ター化する必要があります。 Listはraw型です。総称型ArrayList<E>への参照は、パラメ-ター化する必要があります。」と いうエラーが出ます。 どのように修正してやればいいのでしょうか。 ================================================================================ public void ShuffleTest() { List c = new ArrayList() ; for ( int i = 0 ; i < 9 ; ++ i ) { c.add( new Integer( i ) ) ; } Collections.shuffle(c); // [?�?�?�?�] int j = -1 ; for ( int i = 0 ; i < 9 ; ++ i ) { // toString(c.get( i )) ; System.out.print( c.get( i ) + " " ) ; int k = j + 1 ; s_Oder[ k ] = i ; System.out.print( "s_Oder["+ k + "] =" + i ) ; } }

    • ベストアンサー
    • Java
  • エラーを解決したいんですが。

    // Genericsを用いたArrayListを使用し // ループ処理にはiteratorを使用しない。 // for文を使ってリスト中身が奇数の場合はそのまま画面表示。 // 偶数の場合は-1をかけてから画面表示。 import java.util.ArrayList; class Test{ public static void main(String[] args) { //GenericsのInteger型でArrayListのインスタンスを生成 ArrayList<Integer> array = new ArrayList<Integer>(); array.add(1); array.add(2); array.add(3); array.add(4); array.add(5); for(int i=0; i<array.size(); i++) { Integer integer = array.get( i ); //もし値が偶数だったら if(integer % 2 == 0){ integer *= -1; System.out.println( integer ); } //(それ以外)もし値が奇数だったら else{ System.out.println( integer ); } } } } 上記のプログラムで、 >Integer integer = array.get( i ); の場所が、「交換性がない型」と言われ、エラーになってしまうんですが どうしたらいいですか?

    • ベストアンサー
    • Java
  • ArrayList で配列を扱う場合の記述方法について

    ArrayList で配列を扱う場合の記述方法について、 探しきれないのでご教授お願いします。 ArrayList list = new ArrayList(); list.add("AAA"); list.add("BBB"); list.add("CCC"); for (int i = 0; i < list.size(); i++) { System.out.println(i+"は"+list.get(i)); } という箇所をArrayList<Date>listを使って書き直すのはどのようになるでしょうか。 ArrayList<Date>list= new ArrayList<Date>(); list.add("AAA"); list.add("BBB"); list.add("CCC"); for (int i = 0; i < list.size(); i++) { System.out.println(i+"は"+list.get(i)); } とすると、 型 ArrayList<Date> のメソッド add(Date) は引数 (String) に適用できません。 というエラーになってしまいました。

    • ベストアンサー
    • Java
  • JSPとJavaBeansについて

    JSPとJavaBeansを用いて情報を共有したいと考えています。 値を取得した後に配列に入れています。 ArrayList list = new ArrayList(); while(rs.next()){ int op = rs.getInt("op"); list.add(new Integer(op)); } int[] in = new int[list.size()]; for (int i = 0; i < list.size(); i++) { in[i] = ((Integer)list.get(i)).intValue(); この後に、in[i]の要素をBeansに送り、別のJSPでその値を使いたいと考えています。 ただ、Beansで配列のデータを扱う場合にはどのようにすれば宜しいのでしょうか? アドバイスを頂けると助かります。 宜しくお願いします。

  • arraylist 二次元配列

    こんにちは 今アレイリストの二次元配列を学習しています DBからデータを取得で表示したいと思っています そこでfor文の拡張とつかうとうまくいうのですが 普通に記述するとうまくいきません 拡張FOR 文を使うのは初めてなので 何が違うかアドバイスお願いします コンパイルできません↓ if(request.getAttribute("list")!=null || request.getAttribute("list1")!=null || request.getAttribute("list2")!=null){ ArrayList<ArrayList> hai = new ArrayList<ArrayList>(); ArrayList list = (ArrayList)request.getAttribute("list"); if (list != null) { hai.add(list); } ArrayList list1 = (ArrayList)request.getAttribute("list1"); if (list1 != null) { hai.add(list1); } ArrayList list2 = (ArrayList)request.getAttribute("list2"); if (list2 != null) { hai.add(list2); } for (int i = 0; i < hai.get(0).size(); i++) { %> <table border="3"> <tr> <% for (int k = 0 ; k <= hai.size(); k++) { %> <td width="60"> <% out.print(hai.get(i)); } %> コンパイルOK 表示できています <% if(request.getAttribute("list")!=null || request.getAttribute("list1")!=null || request.getAttribute("list2")!=null){ ArrayList<ArrayList> hai = new ArrayList<ArrayList>(); ArrayList list = (ArrayList)request.getAttribute("list"); if (list != null) { hai.add(list); } ArrayList list1 = (ArrayList)request.getAttribute("list1"); if (list1 != null) { hai.add(list1); } ArrayList list2 = (ArrayList)request.getAttribute("list2"); if (list2 != null) { hai.add(list2); } for (int i = 0; i < hai.get(0).size(); i++) { %> <table border="3"> <tr> <% for (ArrayList list4 : hai) { %> <td width="60"> <% out.print(list4.get(i)); } %> <br> </tr> </table> <% 上のソースの エラーメッセージ 2013/04/16 9:24:12 org.apache.catalina.core.ApplicationDispatcher invoke 致命的: サーブレット jsp のServlet.service()が例外を投げました java.lang.IndexOutOfBoundsException: Index: 2, Size: 2 よろしくお願いします

    • ベストアンサー
    • Java
  • ソートについて

    以下のプログラムを実行すると整数のソート結果が "1","12","3"となってしまいます。 整数と文字列を分離させてそれぞれソートさせたいのですが 方法がわかりません。 import java.util.*; import java.io.*; class StrArray{ ArrayList list = new ArrayList(); //最下行に要素を追加 public void add(String data){ list.add(data); } //全ての要素を配列で所得 public String[] getAll(){ String[] all = new String[list.size()]; for(int i=0; i<list.size(); i++){ all[i] = super.get(i); } return all; } public static final int ASC_SORT = 0; public void sort(int mode){ ArrayList al = this.qsort(mode, list); al = list; } //クイックソート public ArrayList qsort(int mode, ArrayList data){ ArrayList result = new ArrayList(); if(data.size()<1){ return new ArrayList(); } String middle = (String)data.get(data.size()/2); ArrayList left = new ArrayList(); ArrayList right = new ArrayList(); for(int i=0; i<data.size(); i++){ if(i != data.size()/2){ if(mode == 0){ if(((String)data.get(i)).compareTo(middle)<=0){ left.add(data.get(i)); } else{ right.add(data.get(i)); } result.addAll(qsort(0, left)); result.add(middle); result.addAll(qsort(0, right)); return result; } return result; } } } } class Sample{ public static void main(String args[]){ StrArray alist = new StrArray(); alist.add("bbb"); alist.add("aaa"); alist.add("ddd"); alist.add("ccc"); alist.add("3"); alist.add("1"); alist.add("12"); alist.sort(0); String[] info = alist.getAll(); for(int i = 0; i < info.length; i++){ System.out.println(info[i]); } } }

専門家に質問してみよう