静岡理工科大学 菅沼ホーム 目次 索引

分割法( TSP )

    1. A. C++
    2. B. Java
    3. C. PHP
    4. D. Ruby
    5. E. Python
    6. F. C#
    7. G. VB

  プログラム(使用方法)は,巡回セールスマン問題( TSP )を分割法によって解くためのものです.なお,このプログラムは,クラスを使用して記述しています.

  1. C++

      C++11 においては,「メルセンヌ・ツイスター法による擬似乱数生成エンジン」を使用することができます.
    /****************************/
    /* 巡回セールスマン問題     */
    /* (分割法)               */
    /*      coded by Y.Suganuma */
    /****************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <time.h>
    #include "MT.h"
    
    float kyori(int, int *, float **);
    
    /*************************/
    /* クラスPartitionの定義 */
    /*************************/
    class Partition {
    		float **city;   //都市の位置データ
    		float **city_i;   //都市の位置データ(作業領域)
    		float *p_x;   // x軸の分割点
    		float *p_y;   // y軸の分割点
    		float **rg;   // 都市間の距離
    		long seed;   // 乱数の初期値
    		int fix;   // =1 : 近傍を固定
                       // =0 : 近傍を可変
    		int max_try;   // 最大試行回数
    		int n_city;   // 都市の数
    		int **n_seq;   // 各領域の都市数
    		int **n_seq1;   // 各領域の都市数(ワーク)
    		int n_p_x;   // x軸方向の分割数
    		int n_p_y;   // y軸方向の分割数
    		int ***seq;   // 経路
    		int ***seq1;   // 経路(ワーク)
    		int *seq_w1;   // 作業領域
    		int *seq_w2;   // 作業領域
    		int neib;   // 近傍(2 or 3)
    		int seisu;   // 位置データの表現方法
                         //   =1 : 整数
                         //   =-1 : 実数(距離を整数計算)
                         //   =-2 : 実数(距離を実数計算)
    		int sel;   // エッジの選択方法
                       //   =0 : 最良のものを選択
                       //   =1 : 最初のものを選択
    		int **state;   // 領域結合用ワーク
    		char *i_file;   // 入力ファイル名
    	public:
    		int Max;   // 最適経路の長さ
    		int out_m;   // 出力方法
                         //   =-1 : ディスプレイ(経路長だけ)
                         //   =0 : ディスプレイ
                         //   =1 : ファイル
                         //   =2 : ファイル(経路長だけ)
    		char o_file[100];   // 出力ファイル名
    		Partition(char *);   // コンストラクタ
    		Partition();   // コンストラクタ
    		~Partition();   // デストラクタ
    		void Optimize(long);   // 最適化の実行
    		void Output(int, int);   // 出力
    		int Connect();   // 分割したものを一つにまとめる
    };
    
    /*************************/
    /* クラスIterationの定義 */
    /*************************/
    class Iteration {
    		float **city;   //都市の位置データ
    		float **rg;   // 都市間の距離
    		int fix;   // =1 : 近傍を固定
                       // =0 : 近傍を可変
    		int max_try;   // 最大試行回数
    		int n_city;   // 都市の数
    		int out_d;   // 表示間隔
    		int *seq_w1;   // 都市を訪れる順序(ワーク)
    		int *seq_w2;   // 都市を訪れる順序(ワーク)
    		int *seq_w3;   // 都市を訪れる順序(ワーク)
    		int *seq_w4;   // 都市を訪れる順序(ワーク)
    		int *seq_w5;   // 都市を訪れる順序(ワーク)
    		int neib;   // 近傍(2 or 3)
    		int out_lvl;   // 出力レベル
                           //   =0 : 最終出力だけ
                           //   n>0 : n世代毎に出力(負の時はファイル)
    		int out_m;   // 出力方法
                         //   =-1 : 出力しない
                         //   =0 : すべてを出力
                         //   =1 : 評価値だけを出力(最終結果だけはすべてを出力)
    		int seisu;   // 位置データの表現方法
                         //   =1 : 整数
                         //   =-1 : 実数(距離を整数計算)
                         //   =-2 : 実数(距離を実数計算)
    		int sel;   // エッジの選択方法
                       //   =0 : 最良のものを選択
                       //   =1 : 最初のものを選択
    		char o_file[100];   // 出力ファイル名
    	public:
    		int *seq;   // 都市を訪れる順序
    		Iteration (int, int, int, int, int, int, int, int, int, char *, float **);// コンストラクタ
    		~Iteration();   // デストラクタ
    		int Optimize();   // 最適化の実行
    		int Change(double *);   // 改善
    		void Output(int, int, double);   // 出力
    };
    
    /**************************/
    /* コンストラクタ         */
    /*      name : ファイル名 */
    /**************************/
    Partition::Partition(char *name)
    {
    	double x, y;
    	float max_x, max_y, min_x, min_y, s_x, s_y;
    	int i1, i2, i3, max = 0, n;
    	FILE *in;
    					// ファイルのオープン
    	i_file = name;
    	in     = fopen(name, "r");
    	if (in == NULL) {
    		printf("***error  データファイル名が不適当\n");
    		exit(1);
    	}
    					// 基本データ
    	fscanf(in, "%*s %d %*s %d %*s %d %*s %d", &n_city, &sel, &neib, &seisu);
    	fscanf(in, "%*s %d %*s %s", &out_m, o_file);
    	fscanf(in, "%*s %*s %d %*s %d %*s %d", &n_p_x, &n_p_y, &max_try);
    
    	if (neib < 0) {
    		neib = -neib;
    		fix  = 0;
    	}
    	else
    		fix = 1;
    					// 都市の位置データ
    	city = new float * [n_city];
    	for (i1 = 0; i1 < n_city; i1++) {
    		city[i1] = new float [2];
    		fscanf(in, "%f %f", &city[i1][0], &city[i1][1]);
    	}
    					// ファイルのクローズ
    	fclose(in);
    					// 距離テーブルの作成
    	rg = new float * [n_city];
    
    	for (i1 = 0; i1 < n_city; i1++) {
    		rg[i1] = new float [n_city];
    		for (i2 = i1+1; i2 < n_city; i2++) {
    			x          = city[i2][0] - city[i1][0];
    			y          = city[i2][1] - city[i1][1];
    			rg[i1][i2] = (float)sqrt(x * x + y * y);
    			if (seisu > -2)
    				rg[i1][i2] = (int)(rg[i1][i2] + 0.5);
    		}
    	}
    
    	for (i1 = 1; i1 < n_city; i1++) {
    		for (i2 = 0; i2 < i1; i2++)
    			rg[i1][i2] = rg[i2][i1];
    	}
    					// 作業領域
    	state  = new int * [n_p_y];
    	n_seq  = new int * [n_p_y];
    	n_seq1 = new int * [n_p_y];
    	for (i1 = 0; i1 < n_p_y; i1++) {
    		n_seq[i1]  = new int [n_p_x];
    		n_seq1[i1] = new int [n_p_x];
    		state[i1]  = new int [n_p_x];
    	}
    
    	seq  = new int ** [n_p_y];
    	seq1 = new int ** [n_p_y];
    	for (i1 = 0; i1 < n_p_y; i1++) {
    		seq[i1]  = new int * [n_p_x];
    		seq1[i1] = new int * [n_p_x];
    	}
    
    	seq_w1 = new int [n_city];
    	seq_w2 = new int [n_city];
    	p_x    = new float [n_p_x];
    	p_y    = new float [n_p_y];
    					// 都市の分割
    	for (i1 = 0; i1 < n_city; i1++)
    		seq_w1[i1] = 0;
    
    	min_x = city[0][0];
    	max_x = city[0][0];
    	min_y = city[0][1];
    	max_y = city[0][1];
    
    	for (i1 = 1; i1 < n_city; i1++) {
    		if (city[i1][0] < min_x)
    			min_x = city[i1][0];
    		else {
    			if (city[i1][0] > max_x)
    				max_x = city[i1][0];
    		}
    		if (city[i1][1] < min_y)
    			min_y = city[i1][1];
    		else {
    			if (city[i1][1] > max_y)
    				max_y = city[i1][1];
    		}
    	}
    
    	s_x          = (max_x - min_x) / n_p_x;
    	p_x[0]       = min_x + s_x;
    	p_x[n_p_x-1] = max_x;
    	for (i1 = 1; i1 < n_p_x-1; i1++)
    		p_x[i1] = p_x[0] + i1 * s_x;
    
    	s_y = (max_y - min_y) / n_p_y;
    	p_y[0]       = min_y + s_y;
    	p_y[n_p_y-1] = max_y;
    	for (i1 = 1; i1 < n_p_y-1; i1++)
    		p_y[i1] = p_y[0] + i1 * s_y;
    
    	for (i1 = 0; i1 < n_p_y; i1++) {
    		for (i2 = 0; i2 < n_p_x; i2++) {
    			n = 0;
    			for (i3 = 0; i3 < n_city; i3++) {
    				if (seq_w1[i3] == 0) {
    					if (city[i3][0] <= p_x[i2] && city[i3][1] <= p_y[i1]) {
    						seq_w1[i3] = 1;
    						seq_w2[n]  = i3;
    						n++;
    					}
    				}
    			}
    			n_seq1[i1][i2] = n;
    			if (n > 0) {
    				seq[i1][i2]  = new int [n_city];
    				seq1[i1][i2] = new int [n_city];
    				for (i3 = 0; i3 < n; i3++)
    					seq1[i1][i2][i3] = seq_w2[i3];
    				if (n > max)
    					max = n;
    			}
    		}
    	}
    					// 作業領域
    	printf("最大都市数 %d\n", max);
    	city_i = new float * [max];
    	for (i1 = 0; i1 < max; i1++)
    		city_i[i1] = new float [2];
    }
    
    /******************/
    /* コンストラクタ */
    /******************/
    Partition::Partition()
    {
    	n_city = 0;
    }
    
    /****************/
    /* デストラクタ */
    /****************/
    Partition::~Partition()
    {
    	int i1, i2;
    
    	if (n_city > 0) {
    
    		for (i1 = 0; i1 < n_city; i1++) {
    			delete [] rg[i1];
    			delete [] city[i1];
    			delete [] city_i[i1];
    		}
    		delete [] rg;
    		delete [] city;
    		delete [] city_i;
    
    		for (i1 = 0; i1 < n_p_y; i1++)
    			delete [] state[i1];
    		delete [] state;
    
    		delete [] seq_w1;
    		delete [] seq_w2;
    		delete [] p_x;
    		delete [] p_y;
    
    		for (i1 = 0; i1 < n_p_y; i1++) {
    			for (i2 = 0; i2 < n_p_x; i2++) {
    				if (n_seq1[i1][i2] > 0) {
    					delete [] seq[i1][i2];
    					delete [] seq1[i1][i2];
    				}
    			}
    			delete [] seq[i1];
    			delete [] seq1[i1];
    		}
    		delete [] seq;
    		delete [] seq1;
    
    		for (i1 = 0; i1 < n_p_y; i1++) {
    			delete [] n_seq[i1];
    			delete [] n_seq1[i1];
    		}
    		delete [] n_seq;
    		delete [] n_seq1;
    	}
    }
    
    /******************************/
    /* 最適化の実行               */
    /*      seed_i : 乱数の初期値 */
    /******************************/
    void Partition::Optimize(long seed_i)
    {
    	int i1, i2, i3, k, max, nb, r = 0;
    	Iteration *it;
    					// 初期設定
    	seed = seed_i;
    	init_genrand(seed);
    					// 分割数と開始時間の出力
    	if (out_m > 0)
    		Output(0, r);
    
    	for (i1 = 0; i1 < n_p_y; i1++) {
    		for (i2 = 0; i2 < n_p_x; i2++) {
    			n_seq[i1][i2] = n_seq1[i1][i2];
    			for (i3 = 0; i3 < n_seq1[i1][i2]; i3++)
    				seq[i1][i2][i3] = seq1[i1][i2][i3];
    		}
    	}
    					// 分割毎の最適化
    	for (i1 = 0; i1 < n_p_y; i1++) {
    		for (i2 = 0; i2 < n_p_x; i2++) {
    			if (n_seq[i1][i2] > 3) {
    						// 近傍の大きさ
    				nb = (n_seq[i1][i2] > 3) ? neib : 2;
    						// 都市位置データの設定
    				for (i3 = 0; i3 < n_seq[i1][i2]; i3++) {
    					k             = seq[i1][i2][i3];
    					city_i[i3][0] = city[k][0];
    					city_i[i3][1] = city[k][1];
    				}
    						// 最適化
    				it  = new Iteration (n_seq[i1][i2], max_try, seisu, sel, nb, fix,
                                         0, -1, 0, o_file, city_i);
    				max = it->Optimize();
    						// 結果の保存
    				for (i3 = 0; i3 < n_seq[i1][i2]; i3++) {
    					k          = it->seq[i3];
    					seq_w1[i3] = seq[i1][i2][k];
    				}
    				for (i3 = 0; i3 < n_seq[i1][i2]; i3++)
    					seq[i1][i2][i3] = seq_w1[i3];
    						// 出力
    				r = (seisu > -2) ? (int)kyori(n_seq[i1][i2], seq[i1][i2], rg) :
                                       (int)(kyori(n_seq[i1][i2], seq[i1][i2], rg) + 0.5);
    				printf("   y %d x %d n_city %d range %d (trial %d)\n",
                           i1+1, i2+1, n_seq[i1][i2], r, max);
    			}
    		}
    	}
    					// 経路の接続
    	r = Connect();
    					// 出力
    	Output(n_city, r);
    }
    
    /***********************/
    /* 出力                */
    /*      n_c : 都市の数 */
    /*      r : 距離       */
    /***********************/
    void Partition::Output(int n_c, int r)
    {
    	int i1, k = 0, n;
    	char *now;
    	time_t aclock;
    	FILE *out;
    
    	if (out_m <= 0) {
    		out = stdout;
    		fprintf(out, "距離 %d\n", r);
    		getchar();
    	}
    	else {
    		time(&aclock);
    		now = ctime(&aclock);
    		out = fopen(o_file, "a");
    		if (n_c > 0) {
    			printf("距離 %d\n", r);
    			fprintf(out, "   距離 %d 時間 %s\n", r, now);
    		}
    		else
    			fprintf(out, "問題 %s 乱数 %ld 分割 %d %d 時間 %s",
                        i_file, seed, n_p_x, n_p_y, now);
    	}
    
    	if (n_c > 0 && (out_m == 0 || out_m == 1)) {
    		for (i1 = 0; i1 < n_c; i1++) {
    			n = seq_w1[i1];
    			if (seisu > 0)
    				fprintf(out, "  %d %d %d\n", n, (int)city[n][0], (int)city[n][1]);
    			else
    				fprintf(out, "  %d %f %f\n", n, city[n][0], city[n][1]);
    			if (out_m == 0) {
    				k++;
    				if (k == 10) {
    					getchar();
    					k = 0;
    				}
    			}
    		}
    	}
    
    	if (out_m > 0)
    		fclose(out);
    }
    
    /************************/
    /* 分割された領域の接続 */
    /************************/
    int Partition::Connect()
    {
    	double wd, wd1, wa1, wa2, min = 0;
    	int i1, i2, i3, i4, k, k1 = 0, k2 = 0, k3 = 0, k4 = 0, min_c = 0, n, r,
            r1 = 0, r2 = 0, r3 = 0, r4 = 0, s1 = 0, s2 = 0, sw = 1;
    /*
         領域が1つの場合
    */
    	if (n_p_x == 1 && n_p_y == 1) {
    		for (i1 = 0; i1 < n_seq[0][0]; i1++)
    			seq_w1[i1] = seq[0][0][i1];
    	}
    /*
         初期設定
    */
    	else {
    
    		for (i1 = 0; i1 < n_p_y; i1++) {
    			for (i2 = 0; i2 < n_p_x; i2++)
    				state[i1][i2] = (n_seq[i1][i2] > 0) ? 0 : 1;
    		}
    /*
         実行
    */
    		while (sw > 0) {
    					// 最小節点領域
    			min_c = n_city;
    			sw    = 0;
    			for (i1 = 0; i1 < n_p_y; i1++) {
    				for (i2 = 0; i2 < n_p_x; i2++) {
    					if (state[i1][i2] == 0 && n_seq[i1][i2] < min_c) {
    						sw    = 1;
    						r1    = i1;
    						r2    = i2;
    						min_c = n_seq[i1][i2];
    					}
    				}
    			}
    					// 結合する対象領域の決定
    			if (sw > 0) {
    				sw = 0;
    				for (i1 = 0; i1 < n_p_y; i1++) {
    					for (i2 = 0; i2 < n_p_x; i2++) {
    						if (state[i1][i2] == 0 && (i1 != r1 || i2 != r2)) {
    								// 節点の数>2
    							if (n_seq[r1][r2] > 1) {
    								for (i3 = 0; i3 < n_seq[r1][r2]; i3++) {
    									k1  = seq[r1][r2][i3];
    									k2  = (i3 == n_seq[r1][r2]-1) ? seq[r1][r2][0] :
                                                                        seq[r1][r2][i3+1];
    									wd1 = rg[k1][k2];
    									for (i4 = 0; i4 < n_seq[i1][i2]; i4++) {
    										k3  = seq[i1][i2][i4];
    										k4  = (i4 == n_seq[i1][i2]-1) ? seq[i1][i2][0] :
                                                                            seq[i1][i2][i4+1];
    										wd  = wd1 + rg[k3][k4];
    										wa1 = rg[k1][k3] + rg[k2][k4];
    										wa2 = rg[k1][k4] + rg[k2][k3];
    										if (sw == 0 || wa1-wd < min) {
    											min = wa1 - wd;
    											r3  = i1;
    											r4  = i2;
    											s1  = (i3 == n_seq[r1][r2]-1) ? 0 : i3 + 1;
    											s2  = (i4 == n_seq[i1][i2]-1) ? 0 : i4 + 1;
    											sw  = -1;
    										}
    										if (sw == 0 || wa2-wd < min) {
    											min = wa2 - wd;
    											r3  = i1;
    											r4  = i2;
    											s1  = i3;
    											s2  = (i4 == n_seq[i1][i2]-1) ? 0 : i4 + 1;
    											sw  = 1;
    										}
    									}
    								}
    							}
    								// 節点の数=1
    							else {
    								k1 = seq[r1][r2][0];
    								if (n_seq[i1][i2] > 1) {
    									for (i4 = 0; i4 < n_seq[i1][i2]; i4++) {
    										k3  = seq[i1][i2][i4];
    										k4  = (i4 == n_seq[i1][i2]-1) ? seq[i1][i2][0] :
                                                                            seq[i1][i2][i4+1];
    										wd  = rg[k3][k4];
    										wa1 = rg[k1][k3] + rg[k1][k4];
    										if (sw == 0 || wa1-wd < min) {
    											min = wa1 - wd;
    											r3  = i1;
    											r4  = i2;
    											s1  = 0;
    											s2  = (i4 == n_seq[i1][i2]-1) ? 0 : i4 + 1;
    											sw  = 1;
    										}
    									}
    								}
    								else {
    									k3  = seq[i1][i2][0];
    									wa1 = rg[k1][k3];
    									if (sw == 0 || wa1 < min) {
    										min = wa1;
    										r3  = i1;
    										r4  = i2;
    										s1  = 0;
    										s2  = 0;
    										sw  = 1;
    									}
    								}
    							}
    						}
    					}
    				}
    					// 領域の結合
    				seq_w1[0] = seq[r1][r2][s1];
    				k         = 1;
    				n         = s2;
    				for (i1 = 0; i1 < n_seq[r3][r4]; i1++) {
    					seq_w1[k] = seq[r3][r4][n];
    					k++;
    					n++;
    					if (n > n_seq[r3][r4]-1)
    						n = 0;
    				}
    				if (sw > 0) {
    					n = s1 + 1;
    					for (i1 = 0; i1 < n_seq[r1][r2]-1; i1++) {
    						if (n > n_seq[r1][r2]-1)
    							n = 0;
    						seq_w1[k] = seq[r1][r2][n];
    						k++;
    						n++;
    					}
    				}
    				else {
    					n = s1 - 1;
    					for (i1 = 0; i1 < n_seq[r1][r2]-1; i1++) {
    						if (n < 0)
    							n = n_seq[r1][r2] - 1;
    						seq_w1[k] = seq[r1][r2][n];
    						k++;
    						n--;
    					}
    				}
    					// 状態の変更
    				n_seq[r1][r2] += n_seq[r3][r4];
    				state[r3][r4]  = 1;
    				for (i1 = 0; i1 < n_seq[r1][r2]; i1++)
    					seq[r1][r2][i1] = seq_w1[i1];
    				sw  = 1;
    			}
    		}
    	}
    
    	r   = (seisu > -2) ? (int)kyori(n_city, seq_w1, rg) :
                             (int)(kyori(n_city, seq_w1, rg) + 0.5);
    	Max = r;
    
    	return r;
    }
    
    /**********************************/
    /* コンストラクタ                 */
    /*      n_city_i : 都市の数       */
    /*      max_try_i : 最大試行回数  */
    /*      sei_i : 整数 or 実数      */
    /*      sel_i : エッジの選択方法  */
    /*      neib_i : 近傍             */
    /*      fix_i : 近傍の扱い方      */
    /*      out_lvl_i : 出力レベル    */
    /*      out_m_i : 出力方法        */
    /*      out_d_i : 表示間隔        */
    /*      o_file_i : 出力ファイル名 */
    /*      city_i : 都市の位置データ */
    /**********************************/
    Iteration::Iteration (int n_city_i, int max_tri_i, int sei_i, int sel_i, int neib_i, int fix_i, 
                          int out_lvl_i, int out_m_i, int out_d_i, char *o_file_i, float **city_i)
    {
    	double x, y;
    	int ct, i1, i2, sw;
    					// 値の設定
    	n_city  = n_city_i;
    	max_try = max_tri_i;
    	seisu   = sei_i;
    	sel     = sel_i;
    	neib    = neib_i;
    	fix     = fix_i;
    	out_lvl = out_lvl_i;
    	out_m   = out_m_i;
    	out_d   = out_d_i;
    
    	strcpy(o_file, o_file_i);
    					// 都市の位置データ
    	city = new float * [n_city];
    	for (i1 = 0; i1 < n_city; i1++) {
    		city[i1]    = new float [2];
    		city[i1][0] = city_i[i1][0];
    		city[i1][1] = city_i[i1][1];
    	}
    					// 距離テーブルの作成
    	rg = new float * [n_city];
    
    	for (i1 = 0; i1 < n_city; i1++) {
    		rg[i1] = new float [n_city];
    		for (i2 = i1+1; i2 < n_city; i2++) {
    			x          = city[i2][0] - city[i1][0];
    			y          = city[i2][1] - city[i1][1];
    			rg[i1][i2] = (float)sqrt(x * x + y * y);
    			if (seisu > -2)
    				rg[i1][i2] = (int)(rg[i1][i2] + 0.5);
    		}
    	}
    
    	for (i1 = 1; i1 < n_city; i1++) {
    		for (i2 = 0; i2 < i1; i2++)
    			rg[i1][i2] = rg[i2][i1];
    	}
    					// 都市を訪れる順序(初期設定)
    	seq    = new int [n_city];
    	seq_w1 = new int [n_city];
    	seq_w2 = new int [n_city];
    	seq_w3 = new int [n_city];
    	seq_w4 = new int [n_city];
    	seq_w5 = new int [n_city];
    
    	for (i1 = 0; i1 < n_city; i1++) {
    		sw = 0;
    		while (sw == 0) {
    			ct = (int)(genrand_real3() * n_city);
    			if (ct >= n_city)
    				ct = n_city - 1;
    			seq[i1] = ct;
    			sw      = 1;
    			for (i2 = 0; i2 < i1 && sw > 0; i2++) {
    				if (ct == seq[i2])
    					sw = 0;
    			}
    		}
    	}
    }
    
    /****************/
    /* デストラクタ */
    /****************/
    Iteration::~Iteration ()
    {
    	int i1;
    
    	if (n_city > 0) {
    
    		for (i1 = 0; i1 < n_city; i1++) {
    			delete [] city[i1];
    			delete [] rg[i1];
    		}
    		delete [] city;
    		delete [] rg;
    
    		delete[] seq;
    		delete [] seq_w1;
    		delete [] seq_w2;
    		delete [] seq_w3;
    		delete [] seq_w4;
    		delete [] seq_w5;
    	}
    }
    
    /****************/
    /* 最適化の実行 */
    /****************/
    int Iteration::Optimize ()
    {
    	double max;
    	int n_tri, sw;
    					// 初期設定
    	n_tri = 0;
    	max   = kyori(n_city, seq, rg);
    
    	if (out_m >= 0 && abs(out_lvl) > 0) {
    		if (seisu > -2)
    			printf("***試行回数 %d 距離 %d\n", n_tri, (int)max);
    		else
    			printf("***試行回数 %d 距離 %f\n", n_tri, max);
    		Output(out_lvl, n_tri, max);
    	}
    					// 実行
    	sw = 1;
    	for (n_tri = 1; n_tri <= max_try && sw > 0; n_tri++) {
    						// 改善
    		sw = Change(&max);
    						// 出力
    		if (out_d > 0 && n_tri%out_d == 0) {
    			if (seisu > -2)
    				printf("***試行回数 %d 距離 %d\n", n_tri, (int)max);
    			else
    				printf("***試行回数 %d 距離 %f\n", n_tri, max);
    		}
    
    		if (out_m >= 0 && abs(out_lvl) > 0) {
    			if (n_tri%abs(out_lvl) == 0)
    				Output(out_lvl, n_tri, max);
    		}
    	}
    					// 最終出力
    	if (out_m >= 0) {
    		n_tri--;
    		if (seisu > -2)
    			printf("***試行回数 %d 距離 %d\n", n_tri, (int)max);
    		else
    			printf("***試行回数 %d 距離 %f\n", n_tri, max);
    		Output(out_lvl, n_tri, max);
    	}
    
    	return n_tri;
    }
    
    /*******************************/
    /* 出力                        */
    /*      sw : >=0 : 出力先未定  */
    /*           < 0 : ファイル    */
    /*      n_tri : 現在の試行回数 */
    /*      r : 距離               */
    /*******************************/
    void Iteration::Output(int sw, int n_tri, double r)
    {
    	int i1, k = 0, n, pr;
    	char *now;
    	time_t aclock;
    	FILE *out;
    
    	if (sw >= 0) {
    		printf("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    		scanf("%d", &pr);
    	}
    	else
    		pr = -1;
    
    	if (pr != 0) {
    
    		if (pr > 0) {
    			out = stdout;
    			getchar();
    		}
    		else {
    			time(&aclock);
    			now = ctime(&aclock);
    			out = fopen(o_file, "a");
    			if (seisu > -2)
    				fprintf(out, "***試行回数 %d 距離 %d 時間 %s\n", n_tri, (int)r, now);
    			else
    				fprintf(out, "***試行回数 %d 距離 %d 時間 %s\n", n_tri, (int)(r+0.5), now);
    		}
    
    		if (out_m == 0) {
    			for (i1 = 0; i1 < n_city; i1++) {
    				n = seq[i1];
    				if (seisu > 0)
    					fprintf(out, "  %d %d %d\n", n, (int)city[n][0], (int)city[n][1]);
    				else
    					fprintf(out, "  %d %f %f\n", n, city[n][0], city[n][1]);
    				if (pr > 0) {
    					k++;
    					if (k == pr) {
    						getchar();
    						k = 0;
    					}
    				}
    			}
    		}
    
    		if (pr <= 0)
    			fclose(out);
    	}
    }
    
    /**************************************/
    /* エッジの入れ替え                   */
    /*      r_m : 距離                    */
    /*      return : =0 : 改善がなかった  */
    /*               =1 : 改善があった    */
    /**************************************/
    int Iteration::Change(double *r_m)
    {
    	double max, max1 = 0.0, r;
    	int ch = 0, i0, i1, i2, i3, i4, k, k1 = 0, k2 = 0, k3, k4,
            n, nn, n1 = 0, n2 = 0, n3, n4, sw = 0, sw1 = 0, sw2;
    
    	max = *r_m;
    
    /*
         近傍を可変
    */
    	if (fix == 0) {
    					// 初期設定(k=2)
    		k = 2;
    		for (i1 = 0; i1 < n_city; i1++) {
    			seq_w4[i1] = seq[i1];
    			seq_w3[i1] = 0;
    		}
    						// 評価
    		sw2 = 0;
    		for (i0 = 0; i0 < n_city-2 && sw2 < 2; i0++) {
    
    			n = (i0 == 0) ? n_city-1 : n_city;
    
    			for (i1 = i0+2; i1 < n && sw2 < 2; i1++) {
    							// 相手の場所
    				k3 = i1;
    				k4 = k3 + 1;
    				if (k4 > n_city-1)
    					k4 = 0;
    							// 順番の入れ替え
    				n3 = -1;
    				for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    					if (seq_w4[i2] == seq[i0+1])
    						n3 = i2 + 1;
    				}
    				nn = n3;
    				n4 = -1;
    				for (i2 = 0; i2 < n_city && n4 < 0; i2++) {
    					if (nn > n_city-1)
    						nn = 0;
    					if (seq_w4[nn] == seq[k3] || seq_w4[nn] == seq[k4])
    						n4 = seq_w4[nn];
    					else
    						nn++;
    				}
    				if (n4 == seq[k4]) {
    					n4 = k3;
    					k3 = k4;
    					k4 = n4;
    				}
    							// 評価
    				seq_w1[0] = seq[k4];
    				seq_w1[1] = seq[i0+1];
    				n4        = -1;
    				nn        = 2;
    				while (n4 < 0) {
    					if (n3 > n_city-1)
    						n3 = 0;
    					seq_w1[nn] = seq_w4[n3];
    					if (seq_w4[n3] == seq[k3])
    						n4 = 1;
    					nn++;
    					n3++;
    				}
    				seq_w1[nn] = seq[i0];
    				nn++;
    				n3 = -1;
    				n4 = -1;
    				for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    					if (seq_w4[i2] == seq[i0]) {
    						n3 = i2 - 1;
    						if (n3 < 0)
    							n3 = n_city - 1;
    					}
    				}
    				while (n4 < 0) {
    					if (seq_w4[n3] == seq[k4])
    						n4 = 1;
    					else {
    						seq_w1[nn] = seq_w4[n3];
    						nn++;
    						n3--;
    						if (n3 < 0)
    							n3 = n_city - 1;
    					}
    				}
    
    				r = kyori(n_city, seq_w1, rg);
    							// 最適値の保存
    				if (sw2 == 0 || r < max1) {
    					sw2  = 1;
    					max1 = r;
    					n1   = k3;
    					n2   = k4;
    					k1   = i0;
    					k2   = i0 + 1;
    					for (i2 = 0; i2 < n_city; i2++)
    						seq_w5[i2] = seq_w1[i2];
    					if (sel > 0 && max1 < max)
    						sw2 = 2;
    				}
    			}
    		}
    						// 最適値の保存と近傍の増加
    		if (sw2 > 0) {
    			if (max1 < max) {
    				sw  = 1;
    				max = max1;
    				for (i1 = 0; i1 < n_city; i1++)
    					seq_w2[i1] = seq_w5[i1];
    			}
    			if (k < neib) {
    				for (i1 = 0; i1 < n_city; i1++)
    					seq_w4[i1] = seq_w5[i1];
    				seq_w3[k1] = 1;
    				seq_w3[k2] = 1;
    				seq_w3[n1] = 1;
    				seq_w3[n2] = 1;
    				k1         = n2;
    				k++;
    			}
    			else
    				sw1 = 1;
    		}
    		else
    			sw1 = 1;
    					// 実行(k>2)
    		while (sw1 == 0) {
    						// 評価
    			sw2 = 0;
    			for (i1 = 0; i1 < n_city; i1++) {
    							// 相手の場所
    				k3 = i1;
    				k4 = k3 + 1;
    				if (k4 > n_city-1)
    					k4 = 0;
    
    				if (seq_w3[k3] == 0 && seq_w3[k4] == 0) {
    							// 順番の入れ替え
    					n3 = -1;
    					for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    						if (seq_w4[i2] == seq[k2])
    							n3 = i2 + 1;
    					}
    					nn = n3;
    					n4 = -1;
    					for (i2 = 0; i2 < n_city && n4 < 0; i2++) {
    						if (nn > n_city-1)
    							nn = 0;
    						if (seq_w4[nn] == seq[k3] || seq_w4[nn] == seq[k4])
    							n4 = seq_w4[nn];
    						else
    							nn++;
    					}
    					if (n4 == seq[k4]) {
    						n4 = k3;
    						k3 = k4;
    						k4 = n4;
    					}
    							// 評価
    					seq_w1[0] = seq[k4];
    					seq_w1[1] = seq[k2];
    					n4        = -1;
    					nn        = 2;
    					while (n4 < 0) {
    						if (n3 > n_city-1)
    							n3 = 0;
    						seq_w1[nn] = seq_w4[n3];
    						if (seq_w4[n3] == seq[k3])
    							n4 = 1;
    						nn++;
    						n3++;
    					}
    					seq_w1[nn] = seq[k1];
    					nn++;
    					n3 = -1;
    					n4 = -1;
    					for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    						if (seq_w4[i2] == seq[k1]) {
    							n3 = i2 - 1;
    							if (n3 < 0)
    								n3 = n_city - 1;
    						}
    					}
    					while (n4 < 0) {
    						if (seq_w4[n3] == seq[k4])
    							n4 = 1;
    						else {
    							seq_w1[nn] = seq_w4[n3];
    							nn++;
    							n3--;
    							if (n3 < 0)
    								n3 = n_city - 1;
    						}
    					}
    
    					r = kyori(n_city, seq_w1, rg);
    							// 最適値の保存
    					if (sw2 == 0 || r < max1) {
    						sw2  = 1;
    						max1 = r;
    						n1   = k3;
    						n2   = k4;
    						for (i2 = 0; i2 < n_city; i2++)
    							seq_w5[i2] = seq_w1[i2];
    					}
    				}
    			}
    						// 最適値の保存と近傍の増加
    			if (sw2 > 0) {
    				if (max1 < max) {
    					sw  = 1;
    					max = max1;
    					for (i1 = 0; i1 < n_city; i1++)
    						seq_w2[i1] = seq_w5[i1];
    				}
    				if (k < neib) {
    					for (i1 = 0; i1 < n_city; i1++)
    						seq_w4[i1] = seq_w5[i1];
    					seq_w3[n1] = 1;
    					seq_w3[n2] = 1;
    					k1         = n2;
    					k++;
    				}
    				else
    					sw1 = 1;
    			}
    			else
    				sw1 = 1;
    		}
    	}
    /*
         近傍を固定
    */
    	else {
    		n3  = (int)(genrand_real3() * (n_city - 2));
    		if (n3 > n_city-3)
    			n3 = n_city - 3;
                             // 2近傍
    		for (i1 = 0; i1 <= n_city-3 && ch == 0; i1++) {
    
    			if (n3 == 0)
    				n1 = n_city - 2;
    			else
    				n1 = n_city - 1;
    
    			for (i2 = n3+2; i2 <= n1 && ch == 0; i2++) {
                                  // 枝の場所((n3,n3+1), (k1,k2))
    				k1 = i2;
    				if (i2 == n_city-1)
    					k2 = 0;
    				else
    					k2 = i2 + 1;
                                  // 枝の入れ替え
    				seq_w1[0] = seq[n3];
    				k         = 1;
    				for (i3 = k1; i3 >= n3+1; i3--) {
    					seq_w1[k] = seq[i3];
    					k++;
    				}
    
    				nn = k2;
    				while (nn != n3) {
    					seq_w1[k] = seq[nn];
    					k++;
    					nn++;
    					if (nn > n_city-1)
    						nn = 0;
    				}
                                  // 評価
    				r = kyori(n_city, seq_w1, rg);
    
    				if (r < max) {
    					max = r;
    					sw  = 1;
    					for (i3 = 0; i3 < n_city; i3++)
    						seq_w2[i3] = seq_w1[i3];
    					if (sel > 0)
    						ch = 1;
    				}
    			}
    
    			n3++;
    			if (n3 > n_city-3)
    				n3 = 0;
    		}
                             // 3近傍
    		if (neib == 3 && ch == 0) {
    
    			for (i1 = 0; i1 <= n_city-3 && ch == 0; i1++) {
    
    				n1 = n_city - 2;
    				n2 = n_city - 1;
    
    				for (i2 = n3+1; i2 <= n1 && ch == 0; i2++) {
    
    					for (i3 = i2+1; i3 <= n2 && ch == 0; i3++) {
                                  // 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2))
    						k1 = i3;
    						if (i3 == n_city-1)
    							k2 = 0;
    						else
    							k2 = i3 + 1;
                                  // 枝の入れ替えと評価
                                       // 入れ替え(その1)
    						seq_w1[0] = seq[n3];
    						k         = 1;
    						for (i4 = i2; i4 >= n3+1; i4--) {
    							seq_w1[k] = seq[i4];
    							k++;
    						}
    
    						for (i4 = k1; i4 >= i2+1; i4--) {
    							seq_w1[k] = seq[i4];
    							k++;
    						}
    
    						nn = k2;
    						while (nn != n3) {
    							seq_w1[k] = seq[nn];
    							k++;
    							nn++;
    							if (nn > n_city-1)
    								nn = 0;
    						}
                                       // 評価(その1)
    						r = kyori(n_city, seq_w1, rg);
    
    						if (r < max) {
    							max = r;
    							sw  = 1;
    							for (i3 = 0; i3 < n_city; i3++)
    								seq_w2[i3] = seq_w1[i3];
    							if (sel > 0)
    								ch = 1;
    						}
                                       // 入れ替え(その2)
    						seq_w1[0] = seq[n3];
    						k         = 1;
    						for (i4 = k1; i4 >= i2+1; i4--) {
    							seq_w1[k] = seq[i4];
    							k++;
    						}
    
    						for (i4 = n3+1; i4 <= i2; i4++) {
    							seq_w1[k] = seq[i4];
    							k++;
    						}
    
    						nn = k2;
    						while (nn != n3) {
    							seq_w1[k] = seq[nn];
    							k++;
    							nn++;
    							if (nn > n_city-1)
    								nn = 0;
    						}
                                       // 評価(その2)
    						r = kyori(n_city, seq_w1, rg);
    
    						if (r < max) {
    							max = r;
    							sw  = 1;
    							for (i3 = 0; i3 < n_city; i3++)
    								seq_w2[i3] = seq_w1[i3];
    							if (sel > 0)
    								ch = 1;
    						}
                                       // 入れ替え(その3)
    						seq_w1[0] = seq[n3];
    						k         = 1;
    						for (i4 = i2+1; i4 <= k1; i4++) {
    							seq_w1[k] = seq[i4];
    							k++;
    						}
    
    						for (i4 = i2; i4 >= n3+1; i4--) {
    							seq_w1[k] = seq[i4];
    							k++;
    						}
    
    						nn = k2;
    						while (nn != n3) {
    							seq_w1[k] = seq[nn];
    							k++;
    							nn++;
    							if (nn > n_city-1)
    								nn = 0;
    						}
                                       // 評価(その3)
    						r = kyori(n_city, seq_w1, rg);
    
    						if (r < max) {
    							max = r;
    							sw  = 1;
    							for (i3 = 0; i3 < n_city; i3++)
    								seq_w2[i3] = seq_w1[i3];
    							if (sel > 0)
    								ch = 1;
    						}
                                       // 入れ替え(その4)
    						seq_w1[0] = seq[n3];
    						k         = 1;
    						for (i4 = i2+1; i4 <= k1; i4++) {
    							seq_w1[k] = seq[i4];
    							k++;
    						}
    
    						for (i4 = n3+1; i4 <= i2; i4++) {
    							seq_w1[k] = seq[i4];
    							k++;
    						}
    
    						nn = k2;
    						while (nn != n3) {
    							seq_w1[k] = seq[nn];
    							k++;
    							nn++;
    							if (nn > n_city-1)
    								nn = 0;
    						}
                                       // 評価(その4)
    						r = kyori(n_city, seq_w1, rg);
    
    						if (r < max) {
    							max = r;
    							sw  = 1;
    							for (i3 = 0; i3 < n_city; i3++)
    								seq_w2[i3] = seq_w1[i3];
    							if (sel > 0)
    								ch = 1;
    						}
    					}
    				}
    
    				n3++;
    				if (n3 > n_city-3)
    					n3 = 0;
    			}
    		}
    	}
                             // 設定
    	if (sw > 0) {
    		*r_m = max;
    		for (i1 = 0; i1 < n_city; i1++)
    			seq[i1] = seq_w2[i1];
    	}
    
    	return sw;
    }
    
    /*********************************/
    /* 距離の計算                    */
    /*      n_c : 都市の数           */
    /*      p : 都市番号             */
    /*      rg : 都市間の距離        */
    /*      return : 距離            */
    /*********************************/
    float kyori(int n_c, int *p, float **rg)
    {
    	float range = 0;
    	int i1, n1, n2;
    
    	n1 = p[0];
    
    	for (i1 = 1; i1 < n_c; i1++) {
    		n2     = p[i1];
    		range += rg[n1][n2];
    		n1     = n2;
    	}
    
    	n2     = p[0];
    	range += rg[n1][n2];
    
    	return range;
    }
    
    /****************/
    /* main program */
    /****************/
    int main(int argc, char *argv[])
    {
    	double mean;
    	int i0, i1, n, nm, max;
    	char i_file[100];
    	FILE *in, *out;
    	Partition *pt;
    					// 入力ミス
    	if (argc <= 1) {
    		printf("***error  ファイル名を入力して下さい\n");
    		exit(1);
    	}
    					// 入力OK
    	else {
    						// ファイルのオープン
    		in = fopen(argv[1], "r");
    		if (in == NULL) {
    			printf("***error  ファイル名が不適当です\n");
    			exit(1);
    		}
    						// 入力データファイル名と問題数
    		fscanf(in, "%*s %d", &nm);
    
    		for (i0 = 0; i0 < nm; i0++) {
    							// 各問題の実行
    			fscanf(in, "%*s %s %*s %d", i_file, &n);
    			pt   = new Partition(i_file);
    			mean = 0.0;
    			max  = -1;
    								// 乱数の初期値を変える
    			for (i1 = 0; i1 < n; i1++) {
    									// 問題
    				printf("\n+++++問題 %s +++++\n", i_file);
    									// 最適化
    				pt->Optimize(1000 * i1 + 1234567);   // 引数は乱数の初期値
    									// 最適値とその平均の計算
    				mean += pt->Max;
    				if (max < 0 || pt->Max < max)
    					max = pt->Max;
    			}
    							// 結果
    			if (pt->out_m <= 0)
    				printf("     -----最小 %d 平均 %f-----\n", max, mean/n);
    			else {
    				out = fopen(pt->o_file, "a");
    				fprintf(out, "     -----最小 %d 平均 %f-----\n", max, mean/n);
    				fclose(out);
    			}
    		}
    
    		fclose(in);
    	}
    
    	return 0;
    }
    
    //------------------------ケーススタディデータ(data.txt)------
    /*
    問題の数 2
    問題 data1.txt 繰り返し回数 2
    問題 data2.txt 繰り返し回数 1
    */
    //---------------------データファイル(data1.txt)------------
    /*
    都市の数 50 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 2 Y 2 最大試行回数 1000
    86.950684 27.711487
    82.357788 16.148376
    29.791260 37.959290
    27.493286 1.542664
    90.893555 88.734436
    40.109253 92.308044
    87.445068 53.474426
    24.893188 99.382019
    11.633301 80.616760
    61.532593 8.702087
    30.645752 93.598938
    4.714966 81.205750
    86.669922 90.858459
    84.127808 52.830505
    96.893311 45.832825
    4.458618 34.513855
    53.503418 6.959534
    45.394897 12.193298
    23.687744 97.676086
    61.624146 46.806335
    49.633789 16.419983
    82.833862 74.290466
    48.529053 36.628723
    13.711548 5.583191
    12.561035 6.739807
    33.944702 26.622009
    8.917236 50.190735
    98.220825 98.344421
    79.785156 65.419006
    36.227417 56.687927
    42.352295 25.862122
    52.651978 12.590027
    88.806152 79.957581
    27.182007 51.988220
    86.334229 51.142883
    14.505005 35.820007
    77.124023 37.855530
    44.308472 0.022888
    78.363037 13.533020
    21.279907 55.534363
    82.238770 26.612854
    25.106812 88.291931
    55.938721 0.532532
    10.476685 59.233093
    41.650391 33.729553
    7.077026 4.295349
    56.561279 99.641418
    19.595337 34.416199
    92.858887 46.705627
    27.719116 35.533142
    */
    
    //---------------------データファイル(data2.txt)------------
    /*
    都市の数 10 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 1 Y 1 最大試行回数 1000
    8.695068 2.771149
    8.235779 1.614838
    2.979126 3.795929
    2.749329 0.154266
    9.089355 8.873444
    4.010925 9.230804
    8.744507 5.347443
    2.489319 9.938202
    1.163330 8.061676
    6.153259 0.870209
    */
    
    //---------------------MT.h---------------------------
    //   A C-program for MT19937, with initialization improved 2002/1/26.
    //   Coded by Takuji Nishimura and Makoto Matsumoto.
    //
    //   Before using, initialize the state by using init_genrand(seed)  
    //   or init_by_array(init_key, key_length).
    //
    //   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
    //   All rights reserved.                          
    //
    //   Redistribution and use in source and binary forms, with or without
    //   modification, are permitted provided that the following conditions
    //   are met:
    //
    //     1. Redistributions of source code must retain the above copyright
    //        notice, this list of conditions and the following disclaimer.
    //
    //     2. Redistributions in binary form must reproduce the above copyright
    //        notice, this list of conditions and the following disclaimer in the
    //        documentation and/or other materials provided with the distribution.
    //
    //     3. The names of its contributors may not be used to endorse or promote 
    //        products derived from this software without specific prior written 
    //        permission.
    //
    //   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    //   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    //   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    //   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    //   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    //   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    //   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    //   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    //   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    //   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    //   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    //
    //   Any feedback is very welcome.
    //   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
    //   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
    
    
    //   The original version of http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c was modified by Takahiro Omi as
    //   - delete line 47 "#include<stdio.h>"
    //   - delete line 174 int main(void){...}
    //   - change N -> MT_N
    //   - change N -> MT_N
    //   - change the file name "mt19937ar.c" -> "MT.h"
    
    
    /*
    // Period parameters
    #define MT_N 624
    #define MT_M 397
    #define MATRIX_A 0x9908b0dfUL   // constant vector a
    #define UPPER_MASK 0x80000000UL // most significant w-r bits
    #define LOWER_MASK 0x7fffffffUL // least significant r bits
    
    static unsigned long mt[MT_N]; // the array for the state vector
    static int mti=MT_N+1; // mti==MT_N+1 means mt[MT_N] is not initialized
    
    // initializes mt[MT_N] with a seed
    void init_genrand(unsigned long s)
    {
        mt[0]= s & 0xffffffffUL;
        for (mti=1; mti<MT_N; mti++) {
            mt[mti] = 
    	    (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); 
            // See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
            // In the previous versions, MSBs of the seed affect
            // only MSBs of the array mt[].
            // 2002/01/09 modified by Makoto Matsumoto
            mt[mti] &= 0xffffffffUL;
            // for >32 bit machines
        }
    }
    
    // initialize by an array with array-length
    // init_key is the array for initializing keys
    // key_length is its length
    // slight change for C++, 2004/2/26
    void init_by_array(unsigned long init_key[], int key_length)
    {
        int i, j, k;
        init_genrand(19650218UL);
        i=1; j=0;
        k = (MT_N>key_length ? MT_N : key_length);
        for (; k; k--) {
            mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
              + init_key[j] + j; // non linear
            mt[i] &= 0xffffffffUL; // for WORDSIZE > 32 machines
            i++; j++;
            if (i>=MT_N) { mt[0] = mt[MT_N-1]; i=1; }
            if (j>=key_length) j=0;
        }
        for (k=MT_N-1; k; k--) {
            mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
              - i; // non linear
            mt[i] &= 0xffffffffUL; // for WORDSIZE > 32 machines
            i++;
            if (i>=MT_N) { mt[0] = mt[MT_N-1]; i=1; }
        }
    
        mt[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array
    }
    
    // generates a random number on [0,0xffffffff]-interval
    unsigned long genrand_int32(void)
    {
        unsigned long y;
        static unsigned long mag01[2]={0x0UL, MATRIX_A};
        // mag01[x] = x * MATRIX_A  for x=0,1
    
        if (mti >= MT_N) { // generate N words at one time
            int kk;
    
            if (mti == MT_N+1)   // if init_genrand() has not been called,
                init_genrand(5489UL); // a default initial seed is used
    
            for (kk=0;kk<MT_N-MT_M;kk++) {
                y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
                mt[kk] = mt[kk+MT_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
            }
            for (;kk<MT_N-1;kk++) {
                y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
                mt[kk] = mt[kk+(MT_M-MT_N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
            }
            y = (mt[MT_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
            mt[MT_N-1] = mt[MT_M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
    
            mti = 0;
        }
      
        y = mt[mti++];
    
        // Tempering
        y ^= (y >> 11);
        y ^= (y << 7) & 0x9d2c5680UL;
        y ^= (y << 15) & 0xefc60000UL;
        y ^= (y >> 18);
    
        return y;
    }
    
    // generates a random number on [0,0x7fffffff]-interval
    long genrand_int31(void)
    {
        return (long)(genrand_int32()>>1);
    }
    
    // generates a random number on [0,1]-real-interval
    double genrand_real1(void)
    {
        return genrand_int32()*(1.0/4294967295.0); 
        // divided by 2^32-1
    }
    
    // generates a random number on [0,1)-real-interval
    double genrand_real2(void)
    {
        return genrand_int32()*(1.0/4294967296.0); 
        // divided by 2^32
    }
    
    // generates a random number on (0,1)-real-interval
    double genrand_real3(void)
    {
        return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); 
        // divided by 2^32
    }
    
    // generates a random number on [0,1) with 53-bit resolution
    double genrand_res53(void) 
    { 
        unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; 
        return(a*67108864.0+b)*(1.0/9007199254740992.0); 
    } 
    // These real versions are due to Isaku Wada, 2002/01/09 added
    */
    			

  2. Java

      中間結果,及び,最終結果を,図示することが可能です.
    /****************************/
    /* 巡回セールスマン問題     */
    /* (分割法)               */
    /*      coded by Y.Suganuma */
    /****************************/
    import java.io.*;
    import java.util.Random;
    import java.util.Date;
    import java.util.StringTokenizer;
    import java.awt.*;
    import java.awt.event.*;
    
    /*************************/
    /* クラスPartitionの定義 */
    /*************************/
    class Partition {
    	private float [][] rg;   // 都市間の距離
    	private float [] p_x;   // x軸の分割点
    	private float [] p_y;   // y軸の分割点
    	private int fix;   // =1 : 近傍を固定
                           // =0 : 近傍を可変
    	private int max_try;   // 最大試行回数
    	private int [] seq_w1;   // 作業領域
    	private int [] seq_w2;   // 作業領域
    	private int neib;   // 近傍(2 or 3)
    	int seisu;   // 位置データの表現方法
                     //   =1 : 整数
                     //   =-1 : 実数(距離を整数計算)
                     //   =-2 : 実数(距離を実数計算)
    	private int sel;   // エッジの選択方法
                           //   =0 : 最良のものを選択
                           //   =1 : 最初のものを選択
    	private String i_file;   // 入力ファイル名
    	private Win_pt wn;   // Win_itオブジェクト
    	private Random rn;   // 乱数
    
    	float [][] city;   //都市の位置データ
    	float [][] city_i;   //都市の位置データ(作業領域)
    	int Max;   // 最適経路の長さ
    	int n_city;   // 都市の数
    	int [][] n_seq;   // 各領域の都市数
    	int [][] n_seq1;   // 各領域の都市数(ワーク)
    	int n_p_x;   // x軸方向の分割数
    	int n_p_y;   // y軸方向の分割数
    	int out_m;   // 出力方法
                     //   =-1 : ディスプレイ(経路長だけ)
                     //   =0 : ディスプレイ
                     //   =1 : ファイル
                     //   =2 : ファイル(経路長だけ)
    	int range;   // 現在の評価値
    	int seed;   // 乱数の初期値
    	int [][][] seq;   // 経路
    	int [][][] seq1;   // 経路(ワーク)
    	int [][] state;   // 領域結合用ワーク
    	int display;   // 画面表示
                       //   =0 : 画面表示を行わない
                       //   =1 : 結果だけを表示
                       //   =2 : 初期状態と結果を表示
                       //   =3 : 1領域の最適化終了毎に表示
    	String o_file;   // 出力ファイル名
    
    	/**************************/
    	/* コンストラクタ         */
    	/*      name : ファイル名 */
    	/**************************/
    	Partition(String name) throws IOException, FileNotFoundException
    	{
    		double x, y;
    		float max_x, max_y, min_x, min_y, s_x, s_y;
    		int i1, i2, i3, max = 0, n;
    		String line;
    		StringTokenizer dt;
    		BufferedReader in = new BufferedReader(new FileReader(name));
    					// 基本データ
    		i_file = name;
    		line   = in.readLine();
    		dt     = new StringTokenizer(line, " ");
    		dt.nextToken();
    		n_city = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		sel = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		neib = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		seisu = Integer.parseInt(dt.nextToken());
    
    		if (neib < 0) {
    			neib = -neib;
    			fix  = 0;
    		}
    		else
    			fix = 1;
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		out_m = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		o_file = dt.nextToken();
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		dt.nextToken();
    		n_p_x = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		n_p_y = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		max_try = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		display = Integer.parseInt(dt.nextToken());
    
    		line = in.readLine();
    		dt   = new StringTokenizer(line, " ");
    		dt.nextToken();
    		int font = Integer.parseInt(dt.nextToken());
    		dt.nextToken();
    		int width = Integer.parseInt(dt.nextToken());
    		int height = Integer.parseInt(dt.nextToken());
    					// 都市の位置データ
    		city = new float [n_city][2];
    		for (i1 = 0; i1 < n_city; i1++) {
    			line = in.readLine();
    			dt   = new StringTokenizer(line, " ");
    			city[i1][0] = Float.parseFloat(dt.nextToken());
    			city[i1][1] = Float.parseFloat(dt.nextToken());
    		}
    					// ファイルのクローズ
    		in.close();
    					// 距離テーブルの作成
    		rg = new float [n_city][n_city];
    
    		for (i1 = 0; i1 < n_city; i1++) {
    			for (i2 = i1+1; i2 < n_city; i2++) {
    				x          = city[i2][0] - city[i1][0];
    				y          = city[i2][1] - city[i1][1];
    				rg[i1][i2] = (float)Math.sqrt(x * x + y * y);
    				if (seisu > -2)
    					rg[i1][i2] = (int)(rg[i1][i2] + 0.5);
    			}
    		}
    
    		for (i1 = 1; i1 < n_city; i1++) {
    			for (i2 = 0; i2 < i1; i2++)
    				rg[i1][i2] = rg[i2][i1];
    		}
    					// 作業領域
    		state  = new int [n_p_y][n_p_x];
    		n_seq  = new int [n_p_y][n_p_x];
    		n_seq1 = new int [n_p_y][n_p_x];
    
    		seq    = new int [n_p_y][n_p_x][n_city];
    		seq1   = new int [n_p_y][n_p_x][n_city];
    
    		seq_w1 = new int [n_city];
    		seq_w2 = new int [n_city];
    		p_x    = new float [n_p_x];
    		p_y    = new float [n_p_y];
    					// 都市の分割
    		for (i1 = 0; i1 < n_city; i1++)
    			seq_w1[i1] = 0;
    
    		min_x = city[0][0];
    		max_x = city[0][0];
    		min_y = city[0][1];
    		max_y = city[0][1];
    
    		for (i1 = 1; i1 < n_city; i1++) {
    			if (city[i1][0] < min_x)
    				min_x = city[i1][0];
    			else {
    				if (city[i1][0] > max_x)
    					max_x = city[i1][0];
    			}
    			if (city[i1][1] < min_y)
    				min_y = city[i1][1];
    			else {
    				if (city[i1][1] > max_y)
    					max_y = city[i1][1];
    			}
    		}
    
    		s_x          = (max_x - min_x) / n_p_x;
    		p_x[0]       = min_x + s_x;
    		p_x[n_p_x-1] = max_x;
    		for (i1 = 1; i1 < n_p_x-1; i1++)
    			p_x[i1] = p_x[0] + i1 * s_x;
    
    		s_y = (max_y - min_y) / n_p_y;
    		p_y[0]       = min_y + s_y;
    		p_y[n_p_y-1] = max_y;
    		for (i1 = 1; i1 < n_p_y-1; i1++)
    			p_y[i1] = p_y[0] + i1 * s_y;
    
    		for (i1 = 0; i1 < n_p_y; i1++) {
    			for (i2 = 0; i2 < n_p_x; i2++) {
    				n = 0;
    				for (i3 = 0; i3 < n_city; i3++) {
    					if (seq_w1[i3] == 0) {
    						if (city[i3][0] <= p_x[i2] && city[i3][1] <= p_y[i1]) {
    							seq_w1[i3] = 1;
    							seq_w2[n]  = i3;
    							n++;
    						}
    					}
    				}
    				n_seq1[i1][i2] = n;
    				if (n > 0) {
    					for (i3 = 0; i3 < n; i3++)
    						seq1[i1][i2][i3] = seq_w2[i3];
    					if (n > max)
    						max = n;
    				}
    			}
    		}
    
    		for (i1 = 0; i1 < n_p_y; i1++) {
    			for (i2 = 0; i2 < n_p_x; i2++)
    				state[i1][i2] = (n_seq1[i1][i2] > 0) ? 0 : 1;
    		}
    					// 作業領域
    		System.out.println("最大都市数 " + max);
    		city_i = new float [max][2];
    					// Windowの生成
    		if (display > 0)
    			wn = new Win_pt (this, font, width, height);
    	}
    
    	/******************************/
    	/* 最適化の実行               */
    	/*      seed_i : 乱数の初期値 */
    	/******************************/
    	void Optimize(int seed_i) throws IOException, FileNotFoundException
    	{
    		int i1, i2, i3, k, max, nb, r;
    		Iteration it;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    					// 乱数の初期設定
    		seed = seed_i;
    		rn   = new Random (seed);
    
    		for (i1 = 0; i1 < n_p_y; i1++) {
    			for (i2 = 0; i2 < n_p_x; i2++) {
    				n_seq[i1][i2] = n_seq1[i1][i2];
    				state[i1][i2] = (n_seq1[i1][i2] > 0) ? 0 : 1;
    				for (i3 = 0; i3 < n_seq1[i1][i2]; i3++)
    					seq[i1][i2][i3] = seq1[i1][i2][i3];
    			}
    		}
    						// 初期状態の出力(図)
    		if (display >= 2) {
    			wn.Draw(0, -1, -1);
    			System.out.println("      図を確認したらreturnキーを押してください");
    			in.readLine();
    		}
    						// 分割数と開始時間の出力(ファイルへ出力する場合)
    		if (out_m > 0)
    			Output(0);
    						// 分割毎の最適化
    		for (i1 = 0; i1 < n_p_y; i1++) {
    			for (i2 = 0; i2 < n_p_x; i2++) {
    				if (n_seq[i1][i2] > 3) {
    							// 近傍の大きさ
    					nb         = (n_seq[i1][i2] > 3) ? neib : 2;
    							// 都市位置データの設定
    					for (i3 = 0; i3 < n_seq[i1][i2]; i3++) {
    						k             = seq[i1][i2][i3];
    						city_i[i3][0] = city[k][0];
    						city_i[i3][1] = city[k][1];
    					}
    							// 最適化
    					it  = new Iteration (n_seq[i1][i2], max_try, seisu, sel, nb, fix,
                                             0, -1, 0, o_file, city_i, 0, rn);
    					max = it.Optimize();
    							// 結果の保存
    					for (i3 = 0; i3 < n_seq[i1][i2]; i3++) {
    						k          = it.seq[i3];
    						seq_w1[i3] = seq[i1][i2][k];
    					}
    					for (i3 = 0; i3 < n_seq[i1][i2]; i3++)
    						seq[i1][i2][i3] = seq_w1[i3];
    							// 出力(文字)
    					r = (seisu > -2) ? (int)Iteration.kyori(n_seq[i1][i2], seq[i1][i2], rg) :
                                          (int)(Iteration.kyori(n_seq[i1][i2], seq[i1][i2], rg) + 0.5);
    					System.out.print("   y " + (i1+1) + " x " + (i2+1) +
                                         " n_city " + n_seq[i1][i2] +
                                         " range " + r + " (trial " + max + ")\n");
    							// 区分毎最適化結果の出力(図)
    					if (display == 3) {
    						wn.Draw(0, i1, i2);
    						System.out.println("      図を確認したらreturnキーを押してください");
    						in.readLine();
    					}
    				}
    			}
    		}
    						// 経路の接続
    		range = Connect();
    		Max   = range;
    						// 出力(図)
    		if (display > 0) {
    			wn.Draw(1, -1, -1);
    			System.out.println("      図を確認したらreturnキーを押してください");
    			in.readLine();
    		}
    						// 出力(文字)
    		Output(n_city);
    	}
    
    	/***********************/
    	/* 出力                */
    	/*      n_c : 都市の数 */
    	/***********************/
    	void Output(int n_c) throws IOException, FileNotFoundException
    	{
    		int i1, k = 0, n;
    		String now;
    		PrintStream out = null;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    
    		if (out_m <= 0) {
    			out = System.out;
    			out.println("距離 " + range);
    			in.readLine();
    		}
    		else {
    			Date newtime = new Date();   // 現在時刻の獲得
    			now = newtime.toString();    // 文字列への変換
    			out = new PrintStream(new FileOutputStream(o_file, true));
    			if (n_c > 0) {
    				System.out.println("距離 " + range);
    				out.println("   距離 " + range + " 時間 " + now);
    			}
    			else
    				out.println("問題 " + i_file + " 乱数 " + seed + " 分割 " + n_p_x +
                                " " + n_p_y + " 時間 " + now);
    		}
    
    		if (n_c > 0 && (out_m == 0 || out_m == 1)) {
    			for (i1 = 0; i1 < n_c; i1++) {
    				n = seq_w1[i1];
    				if (seisu > 0)
    					out.println("  " + n + " " + (int)city[n][0] + " " + (int)city[n][1]);
    				else
    					out.println("  " + n + " " + city[n][0] + " " + city[n][1]);
    				if (out_m == 0) {
    					k++;
    					if (k == 10) {
    						in.readLine();
    						k = 0;
    					}
    				}
    			}
    		}
    
    		if (out_m > 0)
    			out.close();
    	}
    
    	/************************/
    	/* 分割された領域の接続 */
    	/************************/
    	int Connect() throws IOException
    	{
    		double wd, wd1, wa1, wa2, min = 0;
    		int i1, i2, i3, i4, k, k1 = 0, k2 = 0, k3 = 0, k4 = 0, min_c = 0, n, r,
                r1 = 0, r2 = 0, r3 = 0, r4 = 0, s1 = 0, s2 = 0, sw = 1;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    	/*
    	     領域が1つの場合
    	*/
    		if (n_p_x == 1 && n_p_y == 1) {
    			for (i1 = 0; i1 < n_seq[0][0]; i1++)
    				seq_w1[i1] = seq[0][0][i1];
    		}
    	/*
    	     領域が複数の場合
    	*/
    		else {
    
    			while (sw > 0) {
    						// 最小節点領域
    				min_c = n_city;
    				sw    = 0;
    				for (i1 = 0; i1 < n_p_y; i1++) {
    					for (i2 = 0; i2 < n_p_x; i2++) {
    						if (state[i1][i2] == 0 && n_seq[i1][i2] < min_c) {
    							sw    = 1;
    							r1    = i1;
    							r2    = i2;
    							min_c = n_seq[i1][i2];
    						}
    					}
    				}
    						// 結合する対象領域の決定
    				if (sw > 0) {
    					sw = 0;
    					for (i1 = 0; i1 < n_p_y; i1++) {
    						for (i2 = 0; i2 < n_p_x; i2++) {
    							if (state[i1][i2] == 0 && (i1 != r1 || i2 != r2)) {
    									// 節点の数>2
    								if (n_seq[r1][r2] > 1) {
    									for (i3 = 0; i3 < n_seq[r1][r2]; i3++) {
    										k1  = seq[r1][r2][i3];
    										k2  = (i3 == n_seq[r1][r2]-1) ? seq[r1][r2][0] :
                                                                            seq[r1][r2][i3+1];
    										wd1 = rg[k1][k2];
    										for (i4 = 0; i4 < n_seq[i1][i2]; i4++) {
    											k3  = seq[i1][i2][i4];
    											k4  = (i4 == n_seq[i1][i2]-1) ? seq[i1][i2][0] :
                                                                                seq[i1][i2][i4+1];
    											wd  = wd1 + rg[k3][k4];
    											wa1 = rg[k1][k3] + rg[k2][k4];
    											wa2 = rg[k1][k4] + rg[k2][k3];
    											if (sw == 0 || wa1-wd < min) {
    												min = wa1 - wd;
    												r3  = i1;
    												r4  = i2;
    												s1  = (i3 == n_seq[r1][r2]-1) ? 0 : i3 + 1;
    												s2  = (i4 == n_seq[i1][i2]-1) ? 0 : i4 + 1;
    												sw  = -1;
    											}
    											if (sw == 0 || wa2-wd < min) {
    												min = wa2 - wd;
    												r3  = i1;
    												r4  = i2;
    												s1  = i3;
    												s2  = (i4 == n_seq[i1][i2]-1) ? 0 : i4 + 1;
    												sw  = 1;
    											}
    										}
    									}
    								}
    									// 節点の数=1
    								else {
    									k1 = seq[r1][r2][0];
    									if (n_seq[i1][i2] > 1) {
    										for (i4 = 0; i4 < n_seq[i1][i2]; i4++) {
    											k3  = seq[i1][i2][i4];
    											k4  = (i4 == n_seq[i1][i2]-1) ? seq[i1][i2][0] :
                                                                                seq[i1][i2][i4+1];
    											wd  = rg[k3][k4];
    											wa1 = rg[k1][k3] + rg[k1][k4];
    											if (sw == 0 || wa1-wd < min) {
    												min = wa1 - wd;
    												r3  = i1;
    												r4  = i2;
    												s1  = 0;
    												s2  = (i4 == n_seq[i1][i2]-1) ? 0 : i4 + 1;
    												sw  = 1;
    											}
    										}
    									}
    									else {
    										k3  = seq[i1][i2][0];
    										wa1 = rg[k1][k3];
    										if (sw == 0 || wa1 < min) {
    											min = wa1;
    											r3  = i1;
    											r4  = i2;
    											s1  = 0;
    											s2  = 0;
    											sw  = 1;
    										}
    									}
    								}
    							}
    						}
    					}
    						// 領域の結合
    					seq_w1[0] = seq[r1][r2][s1];
    					k         = 1;
    					n         = s2;
    					for (i1 = 0; i1 < n_seq[r3][r4]; i1++) {
    						seq_w1[k] = seq[r3][r4][n];
    						k++;
    						n++;
    						if (n > n_seq[r3][r4]-1)
    							n = 0;
    					}
    					if (sw > 0) {
    						n = s1 + 1;
    						for (i1 = 0; i1 < n_seq[r1][r2]-1; i1++) {
    							if (n > n_seq[r1][r2]-1)
    								n = 0;
    							seq_w1[k] = seq[r1][r2][n];
    							k++;
    							n++;
    						}
    					}
    					else {
    						n = s1 - 1;
    						for (i1 = 0; i1 < n_seq[r1][r2]-1; i1++) {
    							if (n < 0)
    								n = n_seq[r1][r2] - 1;
    							seq_w1[k] = seq[r1][r2][n];
    							k++;
    							n--;
    						}
    					}
    						// 状態の変更
    					n_seq[r1][r2] += n_seq[r3][r4];
    					state[r3][r4]  = 1;
    					for (i1 = 0; i1 < n_seq[r1][r2]; i1++)
    						seq[r1][r2][i1] = seq_w1[i1];
    					sw  = 1;
    						// 結果の図示
    					if (display == 3) {
    						wn.Draw(0, r1, r2);
    						System.out.println("      図を確認したらreturnキーを押してください");
    						in.readLine();
    					}
    				}
    			}
    		}
    
    		r = (seisu > -2) ? (int)Iteration.kyori(n_city, seq_w1, rg) :
                              (int)(Iteration.kyori(n_city, seq_w1, rg) + 0.5);
    
    		return r;
    	}
    }
    
    /*************************/
    /* クラスIterationの定義 */
    /*************************/
    class Iteration {
    	private float [][] rg;   // 都市間の距離
    	private int fix;   // =1 : 近傍を固定
                           // =0 : 近傍を可変
    	private int max_try;   // 最大試行回数
    	private int neib;   // 近傍(2 or 3)
    	private int out_d;   // 表示間隔
    	private int [] seq_w1;   // 都市を訪れる順序(ワーク)
    	private int [] seq_w2;   // 都市を訪れる順序(ワーク)
    	private int [] seq_w3;   // 都市を訪れる順序(ワーク)
    	private int [] seq_w4;   // 都市を訪れる順序(ワーク)
    	private int [] seq_w5;   // 都市を訪れる順序(ワーク)
    	private int out_lvl;   // 出力レベル
                               //   =0 : 最終出力だけ
                               //   n>0 : n世代毎に出力(負の時はファイル)
    	private int out_m;   // 出力方法
                             //   =-1 : 出力しない
                             //   =0 : すべてを出力
                             //   =1 : 評価値だけを出力(最終結果だけはすべてを出力)
    	int seisu;   // 位置データの表現方法
                     //   =1 : 整数
                     //   =-1 : 実数(距離を整数計算)
                     //   =-2 : 実数(距離を実数計算)
    	private int sel;   // エッジの選択方法
                           //   =0 : 最良のものを選択
                           //   =1 : 最初のものを選択
    	private String o_file;   // 出力ファイル名
    	private Win_it wn;   // Win_itオブジェクト
    	private Random rn;   // 乱数
    
    	double range;   // 現在の評価値
    	float [][] city;   //都市の位置データ
    	int n_city;   // 都市の数
    	int n_tri;   // 試行回数
    	int [] seq;   // 都市を訪れる順序
    	int n_eg;   // 交換した枝の数
    	int [] eg;   // 交換した枝
    	int display;   // 画面表示
                       //   =0 : 画面表示を行わない
                       //   =1 : 結果だけを表示
                       //   =2 : 初期状態と結果を表示
                       //   =3 : ワンステップ毎表示
    
    	/**********************************/
    	/* コンストラクタ                 */
    	/*      n_city_i : 都市の数       */
    	/*      max_try_i : 最大試行回数  */
    	/*      sei_i : 整数 or 実数      */
    	/*      sel_i : エッジの選択方法  */
    	/*      neib_i : 近傍(2 or 3)   */
    	/*      fix_i : 近傍の扱い方      */
    	/*      out_lvl_i : 出力レベル    */
    	/*      out_m_i : 出力方法        */
    	/*      out_d_i : 表示間隔        */
    	/*      o_file_i : 出力ファイル名 */
    	/*      city_i : 都市の位置データ */
    	/*      display_i : 画面表示      */
    	/*      rn_i : 乱数               */
    	/**********************************/
    	Iteration (int n_city_i, int max_tri_i, int sei_i, int sel_i, int neib_i,
                   int fix_i, int out_lvl_i, int out_m_i, int out_d_i, String o_file_i,
                   float [][] city_i, int display_i, Random rn_i)
    	{
    		double x, y;
    		int ct, i1, i2, sw;
    						// 値の設定
    		n_city  = n_city_i;
    		max_try = max_tri_i;
    		seisu   = sei_i;
    		sel     = sel_i;
    		neib    = neib_i;
    		fix     = fix_i;
    		out_lvl = out_lvl_i;
    		out_m   = out_m_i;
    		out_d   = out_d_i;
    		o_file  = o_file_i;
    		display = display_i;
    		rn      = rn_i;
    		n_tri   = 0;
    		n_eg    = 0;
    		eg      = new int [6];
    						// 都市の位置データ
    		city = new float [n_city][2];
    		for (i1 = 0; i1 < n_city; i1++) {
    			city[i1][0] = city_i[i1][0];
    			city[i1][1] = city_i[i1][1];
    		}
    						// 距離テーブルの作成
    		rg = new float [n_city][n_city];
    
    		for (i1 = 0; i1 < n_city; i1++) {
    			for (i2 = i1+1; i2 < n_city; i2++) {
    				x          = city[i2][0] - city[i1][0];
    				y          = city[i2][1] - city[i1][1];
    				rg[i1][i2] = (float)Math.sqrt(x * x + y * y);
    				if (seisu > -2)
    					rg[i1][i2] = (int)(rg[i1][i2] + 0.5);
    			}
    		}
    
    		for (i1 = 1; i1 < n_city; i1++) {
    			for (i2 = 0; i2 < i1; i2++)
    				rg[i1][i2] = rg[i2][i1];
    		}
    						// 都市を訪れる順序(初期設定)
    		seq    = new int [n_city];
    		seq_w1 = new int [n_city];
    		seq_w2 = new int [n_city];
    		seq_w3 = new int [n_city];
    		seq_w4 = new int [n_city];
    		seq_w5 = new int [n_city];
    
    		for (i1 = 0; i1 < n_city; i1++) {
    			sw = 0;
    			while (sw == 0) {
    				ct = (int)(rn.nextDouble() * n_city);
    				if (ct >= n_city)
    					ct = n_city - 1;
    				seq[i1] = ct;
    				sw      = 1;
    				for (i2 = 0; i2 < i1 && sw > 0; i2++) {
    					if (ct == seq[i2])
    						sw = 0;
    				}
    			}
    		}
    	}
    
    	/****************/
    	/* 最適化の実行 */
    	/****************/
    	int Optimize () throws IOException, FileNotFoundException
    	{
    		int sw;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    					// ワンステップづつ実行しない場合
    		if (display < 3) {
    						// 初期設定
    			range = kyori(n_city, seq, rg);
    						// 初期状態の出力(図)
    			if (display == 2) {
    				wn.Draw();
    				System.out.println("   図を確認したらreturnキーを押してください");
    				in.readLine();
    			}
    						// 初期状態の出力(文字)
    			if (out_m >= 0 && Math.abs(out_lvl) > 0) {
    				if (seisu > -2)
    					System.out.println("***試行回数 " + n_tri + " 距離 " + (int)range);
    				else
    					System.out.println("***試行回数 " + n_tri + " 距離 " + range);
    				Output(out_lvl);
    			}
    						// 実行
    			sw = 1;
    			for (n_tri = 1; n_tri <= max_try && sw > 0; n_tri++) {
    							// 改善
    				sw = Change();
    							// 出力(文字)
    				if (out_d > 0 && n_tri%out_d == 0) {
    					if (seisu > -2)
    						System.out.println("***試行回数 " + n_tri + " 距離 " + (int)range);
    					else
    						System.out.println("***試行回数 " + n_tri + " 距離 " + range);
    				}
    
    				if (out_m >= 0 && Math.abs(out_lvl) > 0) {
    					if (n_tri%Math.abs(out_lvl) == 0)
    						Output(out_lvl);
    				}
    			}
    						// 最終出力(図)
    			if (display == 1 || display == 2) {
    				wn.Draw();
    				System.out.println("   図を確認したらreturnキーを押してください");
    				in.readLine();
    			}
    						// 最終出力(文字)
    			if (out_m >= 0) {
    				n_tri--;
    				if (seisu > -2)
    					System.out.println("***試行回数 " + n_tri + " 距離 " + (int)range);
    				else
    					System.out.println("***試行回数 " + n_tri + " 距離 " + (int)(range+0.5));
    				Output(out_lvl);
    			}
    		}
    					// ワンステップづつ実行する場合
    		else {
    						// 初期設定
    			range = kyori(n_city, seq, rg);
    						// 初期状態の出力(図)
    			wn.Draw();
    			System.out.println("   図を確認したらreturnキーを押してください");
    			in.readLine();
    						// 初期状態の出力(文字)
    			if (out_m >= 0 && Math.abs(out_lvl) > 0) {
    				if (seisu > -2)
    					System.out.println("***試行回数 " + n_tri + " 距離 " + (int)range);
    				else
    					System.out.println("***試行回数 " + n_tri + " 距離 " + range);
    				Output(out_lvl);
    			}
    						// マウスによる実行
    			System.out.print("\n終了したらreturnキーを押してください\n");
    			in.readLine();
    						// 最終出力(文字)
    			if (out_m >= 0) {
    				if (seisu > -2)
    					System.out.println("***試行回数 " + n_tri + " 距離 " + (int)range);
    				else
    					System.out.println("***試行回数 " + n_tri + " 距離 " + (int)(range+0.5));
    				Output(out_lvl);
    			}
    		}
    
    		return n_tri;
    	}
    
    	/*******************************/
    	/* 出力                        */
    	/*      sw : >= 0 : 出力先未定 */
    	/*           < 0 : ファイル    */
    	/*******************************/
    	void Output(int sw) throws IOException, FileNotFoundException
    	{
    		int i1, k = 0, n, pr;
    		String now;
    		PrintStream out = null;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    
    		if (sw >= 0) {
    			System.out.print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			pr = Integer.parseInt(in.readLine());
    		}
    		else
    			pr = -1;
    
    		if (pr != 0) {
    
    			if (pr > 0)
    				out = System.out;
    			else {
    				Date newtime = new Date();   // 現在時刻の獲得
    				now = newtime.toString();    // 文字列への変換
    				out = new PrintStream(new FileOutputStream(o_file, true));
    				if (seisu > -2)
    					out.println("***試行回数 " + n_tri + " 距離 " + (int)range + " 時間 " + now);
    				else
    					out.println("***試行回数 " + n_tri + " 距離 " + (int)(range+0.5) +
                                    " 時間 " + now);
    			}
    
    			if (out_m == 0) {
    				for (i1 = 0; i1 < n_city; i1++) {
    					n = seq[i1];
    					if (seisu > 0)
    						out.println("  " + n + " " + (int)city[n][0] + " " + (int)city[n][1]);
    					else
    						out.println("  " + n + " " + city[n][0] + " " + city[n][1]);
    					if (pr > 0) {
    						k++;
    						if (k == pr) {
    							in.readLine();
    							k = 0;
    						}
    					}
    				}
    			}
    
    			if (pr <= 0)
    				out.close();
    		}
    	}
    
    	/**************************************/
    	/* エッジの入れ替え                   */
    	/*      return : =0 : 改善がなかった  */
    	/*               =1 : 改善があった    */
    	/**************************************/
    	int Change()
    	{
    		double max, max1 = 0.0, r;
    		int ch = 0, i0, i1, i2, i3, i4, k, k1 = 0, k2 = 0, k3, k4,
                n, nn, n1 = 0, n2 = 0, n3, n4, sw = 0, sw1 = 0, sw2;
    
    		max = range;
    /*
         近傍を可変
    */
    		if (fix == 0) {
    					// 初期設定(k=2)
    			k = 2;
    			for (i1 = 0; i1 < n_city; i1++) {
    				seq_w4[i1] = seq[i1];
    				seq_w3[i1] = 0;
    			}
    						// 評価
    			sw2 = 0;
    			for (i0 = 0; i0 < n_city-2 && sw2 < 2; i0++) {
    
    				n = (i0 == 0) ? n_city-1 : n_city;
    
    				for (i1 = i0+2; i1 < n && sw2 < 2; i1++) {
    							// 相手の場所
    					k3 = i1;
    					k4 = k3 + 1;
    					if (k4 > n_city-1)
    						k4 = 0;
    							// 順番の入れ替え
    					n3 = -1;
    					for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    						if (seq_w4[i2] == seq[i0+1])
    							n3 = i2 + 1;
    					}
    					nn = n3;
    					n4 = -1;
    					for (i2 = 0; i2 < n_city && n4 < 0; i2++) {
    						if (nn > n_city-1)
    							nn = 0;
    						if (seq_w4[nn] == seq[k3] || seq_w4[nn] == seq[k4])
    							n4 = seq_w4[nn];
    						else
    							nn++;
    					}
    					if (n4 == seq[k4]) {
    						n4 = k3;
    						k3 = k4;
    						k4 = n4;
    					}
    							// 評価
    					seq_w1[0] = seq[k4];
    					seq_w1[1] = seq[i0+1];
    					n4        = -1;
    					nn        = 2;
    					while (n4 < 0) {
    						if (n3 > n_city-1)
    							n3 = 0;
    						seq_w1[nn] = seq_w4[n3];
    						if (seq_w4[n3] == seq[k3])
    							n4 = 1;
    						nn++;
    						n3++;
    					}
    					seq_w1[nn] = seq[i0];
    					nn++;
    					n3 = -1;
    					n4 = -1;
    					for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    						if (seq_w4[i2] == seq[i0]) {
    							n3 = i2 - 1;
    							if (n3 < 0)
    								n3 = n_city - 1;
    						}
    					}
    					while (n4 < 0) {
    						if (seq_w4[n3] == seq[k4])
    							n4 = 1;
    						else {
    							seq_w1[nn] = seq_w4[n3];
    							nn++;
    							n3--;
    							if (n3 < 0)
    								n3 = n_city - 1;
    						}
    					}
    
    					r = kyori(n_city, seq_w1, rg);
    							// 最適値の保存
    					if (sw2 == 0 || r < max1) {
    						sw2  = 1;
    						max1 = r;
    						n1   = k3;
    						n2   = k4;
    						k1   = i0;
    						k2   = i0 + 1;
    						for (i2 = 0; i2 < n_city; i2++)
    							seq_w5[i2] = seq_w1[i2];
    						if (sel > 0 && max1 < max)
    							sw2 = 2;
    					}
    				}
    			}
    						// 最適値の保存と近傍の増加
    			if (sw2 > 0) {
    				if (max1 < max) {
    					sw  = 1;
    					max = max1;
    					for (i1 = 0; i1 < n_city; i1++)
    						seq_w2[i1] = seq_w5[i1];
    				}
    				if (k < neib) {
    					for (i1 = 0; i1 < n_city; i1++)
    						seq_w4[i1] = seq_w5[i1];
    					seq_w3[k1] = 1;
    					seq_w3[k2] = 1;
    					seq_w3[n1] = 1;
    					seq_w3[n2] = 1;
    					k1         = n2;
    					k++;
    				}
    				else
    					sw1 = 1;
    			}
    			else
    				sw1 = 1;
    					// 実行(k>2)
    			while (sw1 == 0) {
    						// 評価
    				sw2 = 0;
    				for (i1 = 0; i1 < n_city; i1++) {
    							// 相手の場所
    					k3 = i1;
    					k4 = k3 + 1;
    					if (k4 > n_city-1)
    						k4 = 0;
    
    					if (seq_w3[k3] == 0 && seq_w3[k4] == 0) {
    							// 順番の入れ替え
    						n3 = -1;
    						for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    							if (seq_w4[i2] == seq[k2])
    								n3 = i2 + 1;
    						}
    						nn = n3;
    						n4 = -1;
    						for (i2 = 0; i2 < n_city && n4 < 0; i2++) {
    							if (nn > n_city-1)
    								nn = 0;
    							if (seq_w4[nn] == seq[k3] || seq_w4[nn] == seq[k4])
    								n4 = seq_w4[nn];
    							else
    								nn++;
    						}
    						if (n4 == seq[k4]) {
    							n4 = k3;
    							k3 = k4;
    							k4 = n4;
    						}
    							// 評価
    						seq_w1[0] = seq[k4];
    						seq_w1[1] = seq[k2];
    						n4        = -1;
    						nn        = 2;
    						while (n4 < 0) {
    							if (n3 > n_city-1)
    								n3 = 0;
    							seq_w1[nn] = seq_w4[n3];
    							if (seq_w4[n3] == seq[k3])
    								n4 = 1;
    							nn++;
    							n3++;
    						}
    						seq_w1[nn] = seq[k1];
    						nn++;
    						n3 = -1;
    						n4 = -1;
    						for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    							if (seq_w4[i2] == seq[k1]) {
    								n3 = i2 - 1;
    								if (n3 < 0)
    									n3 = n_city - 1;
    							}
    						}
    						while (n4 < 0) {
    							if (seq_w4[n3] == seq[k4])
    								n4 = 1;
    							else {
    								seq_w1[nn] = seq_w4[n3];
    								nn++;
    								n3--;
    								if (n3 < 0)
    									n3 = n_city - 1;
    							}
    						}
    
    						r = kyori(n_city, seq_w1, rg);
    							// 最適値の保存
    						if (sw2 == 0 || r < max1) {
    							sw2  = 1;
    							max1 = r;
    							n1   = k3;
    							n2   = k4;
    							for (i2 = 0; i2 < n_city; i2++)
    								seq_w5[i2] = seq_w1[i2];
    						}
    					}
    				}
    						// 最適値の保存と近傍の増加
    				if (sw2 > 0) {
    					if (max1 < max) {
    						sw  = 1;
    						max = max1;
    						for (i1 = 0; i1 < n_city; i1++)
    							seq_w2[i1] = seq_w5[i1];
    					}
    					if (k < neib) {
    						for (i1 = 0; i1 < n_city; i1++)
    							seq_w4[i1] = seq_w5[i1];
    						seq_w3[n1] = 1;
    						seq_w3[n2] = 1;
    						k1         = n2;
    						k++;
    					}
    					else
    						sw1 = 1;
    				}
    				else
    					sw1 = 1;
    			}
    		}
    /*
         近傍を固定
    */
    		else {
    
    			n3  = (int)(rn.nextDouble() * (n_city - 2));
    			if (n3 > n_city-3)
    				n3 = n_city - 3;
                             // 2近傍
    			for (i1 = 0; i1 <= n_city-3 && ch == 0; i1++) {
    
    				if (n3 == 0)
    					n1 = n_city - 2;
    				else
    					n1 = n_city - 1;
    
    				for (i2 = n3+2; i2 <= n1 && ch == 0; i2++) {
                                  // 枝の場所((n3,n3+1), (k1,k2))
    					k1 = i2;
    					if (i2 == n_city-1)
    						k2 = 0;
    					else
    						k2 = i2 + 1;
                                  // 枝の入れ替え
    					seq_w1[0] = seq[n3];
    					k         = 1;
    					for (i3 = k1; i3 >= n3+1; i3--) {
    						seq_w1[k] = seq[i3];
    						k++;
    					}
    
    					nn = k2;
    					while (nn != n3) {
    						seq_w1[k] = seq[nn];
    						k++;
    						nn++;
    						if (nn > n_city-1)
    							nn = 0;
    					}
                                  // 評価
    					r = kyori(n_city, seq_w1, rg);
    
    					if (r < max) {
    						max = r;
    						sw  = 1;
    						for (i3 = 0; i3 < n_city; i3++)
    							seq_w2[i3] = seq_w1[i3];
    						if (sel > 0)
    							ch = 1;
    						n_eg  = 2;
    						eg[0] = seq[n3];
    						eg[1] = seq[n3+1];
    						eg[2] = seq[k1];
    						eg[3] = seq[k2];
    					}
    				}
    
    				n3++;
    				if (n3 > n_city-3)
    					n3 = 0;
    			}
                             // 3近傍
    			if (neib == 3 && ch == 0) {
    
    				for (i1 = 0; i1 <= n_city-3 && ch == 0; i1++) {
    
    					n1 = n_city - 2;
    					n2 = n_city - 1;
    
    					for (i2 = n3+1; i2 <= n1 && ch == 0; i2++) {
    
    						for (i3 = i2+1; i3 <= n2 && ch == 0; i3++) {
                                  // 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2))
    							k1 = i3;
    							if (i3 == n_city-1)
    								k2 = 0;
    							else
    								k2 = i3 + 1;
                                  // 枝の入れ替えと評価
                                       // 入れ替え(その1)
    							seq_w1[0] = seq[n3];
    							k         = 1;
    							for (i4 = i2; i4 >= n3+1; i4--) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							for (i4 = k1; i4 >= i2+1; i4--) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							nn = k2;
    							while (nn != n3) {
    								seq_w1[k] = seq[nn];
    								k++;
    								nn++;
    								if (nn > n_city-1)
    									nn = 0;
    							}
                                       // 評価(その1)
    							r = kyori(n_city, seq_w1, rg);
    
    							if (r < max) {
    								max = r;
    								sw  = 1;
    								for (i3 = 0; i3 < n_city; i3++)
    									seq_w2[i3] = seq_w1[i3];
    								if (sel > 0)
    									ch = 1;
    								n_eg  = 3;
    								eg[0] = seq[n3];
    								eg[1] = seq[n3+1];
    								eg[2] = seq[i2];
    								eg[3] = seq[i2+1];
    								eg[4] = seq[k1];
    								eg[5] = seq[k2];
    							}
                                       // 入れ替え(その2)
    							seq_w1[0] = seq[n3];
    							k         = 1;
    							for (i4 = k1; i4 >= i2+1; i4--) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							for (i4 = n3+1; i4 <= i2; i4++) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							nn = k2;
    							while (nn != n3) {
    								seq_w1[k] = seq[nn];
    								k++;
    								nn++;
    								if (nn > n_city-1)
    									nn = 0;
    							}
                                       // 評価(その2)
    							r = kyori(n_city, seq_w1, rg);
    
    							if (r < max) {
    								max = r;
    								sw  = 1;
    								for (i3 = 0; i3 < n_city; i3++)
    									seq_w2[i3] = seq_w1[i3];
    								if (sel > 0)
    									ch = 1;
    								n_eg  = 3;
    								eg[0] = seq[n3];
    								eg[1] = seq[n3+1];
    								eg[2] = seq[i2];
    								eg[3] = seq[i2+1];
    								eg[4] = seq[k1];
    								eg[5] = seq[k2];
    							}
                                       // 入れ替え(その3)
    							seq_w1[0] = seq[n3];
    							k         = 1;
    							for (i4 = i2+1; i4 <= k1; i4++) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							for (i4 = i2; i4 >= n3+1; i4--) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							nn = k2;
    							while (nn != n3) {
    								seq_w1[k] = seq[nn];
    								k++;
    								nn++;
    								if (nn > n_city-1)
    									nn = 0;
    							}
                                       // 評価(その3)
    							r = kyori(n_city, seq_w1, rg);
    
    							if (r < max) {
    								max = r;
    								sw  = 1;
    								for (i3 = 0; i3 < n_city; i3++)
    									seq_w2[i3] = seq_w1[i3];
    								if (sel > 0)
    									ch = 1;
    								n_eg  = 3;
    								eg[0] = seq[n3];
    								eg[1] = seq[n3+1];
    								eg[2] = seq[i2];
    								eg[3] = seq[i2+1];
    								eg[4] = seq[k1];
    								eg[5] = seq[k2];
    							}
                                       // 入れ替え(その4)
    							seq_w1[0] = seq[n3];
    							k         = 1;
    							for (i4 = i2+1; i4 <= k1; i4++) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							for (i4 = n3+1; i4 <= i2; i4++) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							nn = k2;
    							while (nn != n3) {
    								seq_w1[k] = seq[nn];
    								k++;
    								nn++;
    								if (nn > n_city-1)
    									nn = 0;
    							}
                                       // 評価(その4)
    							r = kyori(n_city, seq_w1, rg);
    
    							if (r < max) {
    								max = r;
    								sw  = 1;
    								for (i3 = 0; i3 < n_city; i3++)
    									seq_w2[i3] = seq_w1[i3];
    								if (sel > 0)
    									ch = 1;
    								n_eg  = 3;
    								eg[0] = seq[n3];
    								eg[1] = seq[n3+1];
    								eg[2] = seq[i2];
    								eg[3] = seq[i2+1];
    								eg[4] = seq[k1];
    								eg[5] = seq[k2];
    							}
    						}
    					}
    
    					n3++;
    					if (n3 > n_city-3)
    						n3 = 0;
    				}
    			}
    		}
                             // 設定
    		if (sw > 0) {
    			range = max;
    			for (i1 = 0; i1 < n_city; i1++)
    				seq[i1] = seq_w2[i1];
    		}
    
    		return sw;
    	}
    
    	/*********************************/
    	/* 距離の計算                    */
    	/*      n_c : 都市の数           */
    	/*      p : 都市番号             */
    	/*      rg : 都市間の距離        */
    	/*      return : 距離            */
    	/*********************************/
    	static float kyori(int n_c, int [] p, float [][] rg)
    	{
    		float range = 0;
    		int i1, n1, n2;
    
    		n1 = p[0];
    
    		for (i1 = 1; i1 < n_c; i1++) {
    			n2     = p[i1];
    			range += rg[n1][n2];
    			n1     = n2;
    		}
    
    		n2     = p[0];
    		range += rg[n1][n2];
    
    		return range;
    	}
    }
    
    /**********************/
    /* クラスWin_ptの定義 */
    /**********************/
    class Win_pt extends Frame {
    
    	double ritu;   // 表示倍率
    	private float min_x, max_x, min_y, max_y;   // 都市の存在範囲
    	private int font;   // フォントサイズ
    	private int next, yoyu_x, yoyu_y;   // 表示位置
    	private int r_sw;   // 距離表示の有無
    	private int c_x, c_y;   // 現在の対象領域
    	private Partition pt;
    
    	/*************************************/
    	/* コンストラクタ                    */
    	/*      pt : Partitionのオブジェクト */
    	/*      city_i : 都市の位置データ    */
    	/*      font_i : フォントサイズ      */
    	/*      width,height : 表示範囲      */
    	/*************************************/
    	Win_pt (Partition pt_i, int font_i, int width, int height)
    	{
    					// Frameクラスのコンストラクタの呼び出し
    		super("巡回セールスマン問題");
    					// 値の設定と領域の確保
    		double k1, k2;
    		int i1;
    
    		pt      = pt_i;
    		font    = font_i;
    		next    = 70;
    		yoyu_x  = 30;
    		yoyu_y  = 80;
    					// 描画領域の計算
    		min_x = pt.city[0][0];
    		max_x = pt.city[0][0];
    		min_y = pt.city[0][1];
    		max_y = pt.city[0][1];
    
    		for (i1 = 1; i1 < pt.n_city; i1++) {
    			if (pt.city[i1][0] < min_x)
    				min_x = pt.city[i1][0];
    			else {
    				if (pt.city[i1][0] > max_x)
    					max_x = pt.city[i1][0];
    			}
    			if (pt.city[i1][1] < min_y)
    				min_y = pt.city[i1][1];
    			else {
    				if (pt.city[i1][1] > max_y)
    					max_y = pt.city[i1][1];
    			}
    		}
    
    		k1 = (double)(width - 2 * yoyu_x) / (max_x - min_x);
    		if (pt.display == 3)
    			k2 = (double)(height - yoyu_y - next) / (max_y - min_y);
    		else
    			k2 = (double)(height - yoyu_y - yoyu_x) / (max_y - min_y);
    		ritu = (k1 < k2) ? k1 : k2;
    					// Windowサイズ
    		width  = 2 * yoyu_x + (int)(ritu * (max_x - min_x));
    		height = yoyu_y + yoyu_x + (int)(ritu * (max_y - min_y));
    		setSize(width, height);
    					// ウィンドウを表示
    		setVisible(true);
    					// イベントアダプタ
    		addWindowListener(new WinEnd());
    	}
    
    	/********************************/
    	/* 描画指示                     */
    	/*      sw : 距離表示の有無     */
    	/*      c_y_i, c_x_i : 対象領域 */
    	/********************************/
    	void Draw(int sw, int c_y_i, int c_x_i)
    	{
    		r_sw = sw;
    		c_y  = c_y_i;
    		c_x  = c_x_i;
    
    		repaint();
    	}
    
    	/********/
    	/* 描画 */
    	/********/
    	public void paint (Graphics g)
    	{
    		int i1, i2, i3, k, n1, n2, size = 6, x1, x2, y1, y2;
    		Font f;
    						// 距離の表示
    		if (r_sw > 0) {
    			f = new Font("TimesRoman", Font.BOLD, 25);
    			g.setFont(f);
    			if (pt.seisu > -2)
    				g.drawString("Length : "+Integer.toString((int)pt.range), yoyu_x, yoyu_y-30);
    			else
    				g.drawString("Length : "+Integer.toString((int)(pt.range+0.5)), yoyu_x, yoyu_y-30);
    		}
    						// 都市番号のフォントサイズ
    		if (font > 0) {
    			f = new Font("TimesRoman", Font.PLAIN, font);
    			g.setFont(f);
    		}
    					// 点と直線のプロット
    		k = size / 2;
    
    		for (i1 = 0; i1 < pt.n_p_y; i1++) {
    			for (i2 = 0; i2 < pt.n_p_x; i2++) {
    
    				if (pt.state[i1][i2] == 0) {
    
    					if (i1 == c_y && i2 == c_x)
    						g.setColor(Color.red);
    					else
    						g.setColor(Color.black);
    
    					for (i3 = 0; i3 < pt.n_seq[i1][i2]; i3++) {
    
    						n2 = pt.seq[i1][i2][i3];
    						x2 = yoyu_x + (int)(ritu * (pt.city[n2][0] - min_x));
    						y2 = yoyu_y + (int)(ritu * (max_y - pt.city[n2][1]));
    
    						g.fillOval(x2, y2, size, size);
    
    						if (font > 0)
    							g.drawString(Integer.toString(n2), x2+k, y2-k);
    
    						if (i3 > 0) {
    							n1 = pt.seq[i1][i2][i3-1];
    							x1 = yoyu_x + (int)(ritu * (pt.city[n1][0] - min_x));
    							y1 = yoyu_y + (int)(ritu * (max_y - pt.city[n1][1]));
    							g.drawLine(x1+k, y1+k, x2+k, y2+k);
    							if (i3 == pt.n_seq[i1][i2]-1) {
    								n1 = pt.seq[i1][i2][0];
    								x1 = yoyu_x + (int)(ritu * (pt.city[n1][0] - min_x));
    								y1 = yoyu_y + (int)(ritu * (max_y - pt.city[n1][1]));
    								g.drawLine(x1+k, y1+k, x2+k, y2+k);
    							}
    						}
    					}
    				}
    			}
    		}
    	}
    
    	/************/
    	/* 終了処理 */
    	/************/
    	class WinEnd extends WindowAdapter
    	{
    		public void windowClosing(WindowEvent e) {
    			System.exit(0);
    		}
    	}
    }
    
    /**********************/
    /* クラスWin_itの定義 */
    /**********************/
    class Win_it extends Frame {
    
    	double ritu;   // 表示倍率
    	private float min_x, max_x, min_y, max_y;   // 都市の存在範囲
    	private int font;   // フォントサイズ
    	private int next, yoyu_x, yoyu_y;   // 表示位置
    	private Iteration it;
    
    	/***************************************/
    	/* コンストラクタ                      */
    	/*      it_i : Iterationのオブジェクト */
    	/*      font_i : フォントサイズ        */
    	/*      width,height : 表示範囲        */
    	/***************************************/
    	Win_it (Iteration it_i, int font_i, int width, int height)
    	{
    					// Frameクラスのコンストラクタの呼び出し
    		super("巡回セールスマン問題");
    					// 値の設定と領域の確保
    		double k1, k2;
    		int i1;
    
    		it      = it_i;
    		font    = font_i;
    		next    = 70;
    		yoyu_x  = 30;
    		yoyu_y  = 80;
    					// 描画領域の計算
    		min_x = it.city[0][0];
    		max_x = it.city[0][0];
    		min_y = it.city[0][1];
    		max_y = it.city[0][1];
    
    		for (i1 = 1; i1 < it.n_city; i1++) {
    			if (it.city[i1][0] < min_x)
    				min_x = it.city[i1][0];
    			else {
    				if (it.city[i1][0] > max_x)
    					max_x = it.city[i1][0];
    			}
    			if (it.city[i1][1] < min_y)
    				min_y = it.city[i1][1];
    			else {
    				if (it.city[i1][1] > max_y)
    					max_y = it.city[i1][1];
    			}
    		}
    
    		k1 = (double)(width - 2 * yoyu_x) / (max_x - min_x);
    		if (it.display == 3)
    			k2 = (double)(height - yoyu_y - next) / (max_y - min_y);
    		else
    			k2 = (double)(height - yoyu_y - yoyu_x) / (max_y - min_y);
    		ritu = (k1 < k2) ? k1 : k2;
    					// ボタンの設定とWindowサイズ
    		if (it.display == 3) {
    						// パネルクラスの定義
    			Panel pnl = new Panel();
    						// Next ボタンの設定
    			Button bt = new Button("Next");
    			bt.addMouseListener(new ClickMouse());
    			pnl.add(bt);
    			add("South", pnl);
    						// ウィンドウの構成要素をパック
    			pack();
    						// 指定された大きさにWindowサイズを変更
    			width  = 2 * yoyu_x + (int)(ritu * (max_x - min_x));
    			height = yoyu_y + next + (int)(ritu * (max_y - min_y));
    		}
    		else {
    						// 指定された大きさにWindowサイズを変更
    			width  = 2 * yoyu_x + (int)(ritu * (max_x - min_x));
    			height = yoyu_y + yoyu_x + (int)(ritu * (max_y - min_y));
    		}
    
    		setSize(width, height);
    					// ウィンドウを表示
    		setVisible(true);
    					// イベントアダプタ
    		addWindowListener(new WinEnd());
    	}
    
    	/************/
    	/* 描画指示 */
    	/************/
    	void Draw()
    	{
    		repaint();
    	}
    
    	/********/
    	/* 描画 */
    	/********/
    	public void paint (Graphics g)
    	{
    		int i1, k, n1, n2, size = 6, x1, x2, y1, y2;
    		Font f;
    						// 距離の表示
    		f = new Font("TimesRoman", Font.BOLD, 25);
    		g.setFont(f);
    		if (it.seisu > -2)
    			g.drawString("Length : "+Integer.toString((int)it.range), yoyu_x, yoyu_y-30);
    		else
    			g.drawString("Length : "+Integer.toString((int)(it.range+0.5)), yoyu_x, yoyu_y-30);
    						// 都市番号のフォントサイズ
    		if (font > 0) {
    			f = new Font("TimesRoman", Font.PLAIN, font);
    			g.setFont(f);
    		}
    					// 点と直線のプロット
    		k = size / 2;
    
    		for (i1 = 0; i1 < it.n_city; i1++) {
    
    			n2 = it.seq[i1];
    			x2 = yoyu_x + (int)(ritu * (it.city[n2][0] - min_x));
    			y2 = yoyu_y + (int)(ritu * (max_y - it.city[n2][1]));
    
    			g.fillOval(x2, y2, size, size);
    
    			if (font > 0)
    				g.drawString(Integer.toString(n2), x2+k, y2-k);
    
    			if (i1 > 0) {
    				n1 = it.seq[i1-1];
    				x1 = yoyu_x + (int)(ritu * (it.city[n1][0] - min_x));
    				y1 = yoyu_y + (int)(ritu * (max_y - it.city[n1][1]));
    				g.drawLine(x1+k, y1+k, x2+k, y2+k);
    				if (i1 == it.n_city-1) {
    					n1 = it.seq[0];
    					x1 = yoyu_x + (int)(ritu * (it.city[n1][0] - min_x));
    					y1 = yoyu_y + (int)(ritu * (max_y - it.city[n1][1]));
    					g.drawLine(x1+k, y1+k, x2+k, y2+k);
    				}
    			}
    		}
    					// 交換した元の枝を赤く描く
    		if (it.display == 3 && it.n_eg > 0) {
    			g.setColor(Color.red);
    			for (i1 = 0; i1 < it.n_eg; i1++ ) {
    				n1 = it.eg[2*i1];
    				x1 = yoyu_x + (int)(ritu * (it.city[n1][0] - min_x));
    				y1 = yoyu_y + (int)(ritu * (max_y - it.city[n1][1]));
    				n2 = it.eg[2*i1+1];
    				x2 = yoyu_x + (int)(ritu * (it.city[n2][0] - min_x));
    				y2 = yoyu_y + (int)(ritu * (max_y - it.city[n2][1]));
    				g.drawLine(x1+k, y1+k, x2+k, y2+k);
    			}
    		}
    	}
    
    	/**********************************/
    	/* nextボタンが押されたときの処理 */
    	/**********************************/
    	class ClickMouse extends MouseAdapter
    	{
    		/************************************/
    		/* マウスがクリックされたときの処理 */
    		/************************************/
    		public void mouseClicked(MouseEvent e)
    		{
    			int sw = it.Change();
    			if (sw > 0)
    				it.n_tri++;
    			else
    				it.n_eg = 0;
    			repaint();
    		}
    	}
    
    	/************/
    	/* 終了処理 */
    	/************/
    	class WinEnd extends WindowAdapter
    	{
    		public void windowClosing(WindowEvent e) {
    			System.exit(0);
    		}
    	}
    }
    
    public class Test {
    
    	/****************/
    	/* main program */
    	/****************/
    	public static void main(String args[]) throws IOException, FileNotFoundException
    	{
    		double mean;
    		int i0, i1, n, nm, max;
    		String i_file, line;
    		Partition pt;
    		StringTokenizer dt;
    		PrintStream out = null;
    		BufferedReader in = new BufferedReader(new FileReader(args[0]));
    						// 入力ミス
    		if (args.length == 0) {
    			System.out.print("***error  ファイル名を入力して下さい\n");
    			System.exit(1);
    		}
    						// 入力OK
    		else {
    							// 入力データファイル名と問題数
    			line = in.readLine();
    			dt   = new StringTokenizer(line, " ");
    			dt.nextToken();
    			nm = Integer.parseInt(dt.nextToken());
    
    			for (i0 = 0; i0 < nm; i0++) {
    								// 各問題の実行
    				line = in.readLine();
    				dt   = new StringTokenizer(line, " ");
    				dt.nextToken();
    				i_file = dt.nextToken();
    				dt.nextToken();
    				n = Integer.parseInt(dt.nextToken());
    
    				pt   = new Partition(i_file);
    				mean = 0.0;
    				max  = -1;
    									// 乱数の初期値を変える
    				for (i1 = 0; i1 < n; i1++) {
    
    					System.out.println("\n+++++問題 " + i_file + "+++++");
    									// 最適化
    					pt.Optimize(1000 * i1 + 1234567);   // 引数は乱数の初期値
    									// 最適値とその平均の計算
    					mean += pt.Max;
    					if (max < 0 || pt.Max < max)
    						max = pt.Max;
    				}
    							// 結果
    				if (pt.out_m <= 0)
    					System.out.println("     -----最小 " + max + " 平均 " + mean/n + "-----");
    				else {
    					out = new PrintStream(new FileOutputStream(pt.o_file, true));
    					out.println("     -----最小 " + max + " 平均 " + mean/n + "-----");
    					out.close();
    				}
    			}
    
    			in.close();
    		}
    	}
    }
    
    //------------------------ケーススタディデータ(data_j.txt)------
    /*
    問題の数 2
    問題 data1_j.txt 繰り返し回数 2
    問題 data2_j.txt 繰り返し回数 1
    */
    //---------------------データファイル(data1_j.txt)------------
    /*
    都市の数 50 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 2 Y 2 最大試行回数 1000
    図示(0:しない,1:結果,2:初期状態と結果,3:ステップ) 3
    都市番号 0 図の大きさ(幅,高さ) 1000 750
    86.950684 27.711487
    82.357788 16.148376
    29.791260 37.959290
    27.493286 1.542664
    90.893555 88.734436
    40.109253 92.308044
    87.445068 53.474426
    24.893188 99.382019
    11.633301 80.616760
    61.532593 8.702087
    30.645752 93.598938
    4.714966 81.205750
    86.669922 90.858459
    84.127808 52.830505
    96.893311 45.832825
    4.458618 34.513855
    53.503418 6.959534
    45.394897 12.193298
    23.687744 97.676086
    61.624146 46.806335
    49.633789 16.419983
    82.833862 74.290466
    48.529053 36.628723
    13.711548 5.583191
    12.561035 6.739807
    33.944702 26.622009
    8.917236 50.190735
    98.220825 98.344421
    79.785156 65.419006
    36.227417 56.687927
    42.352295 25.862122
    52.651978 12.590027
    88.806152 79.957581
    27.182007 51.988220
    86.334229 51.142883
    14.505005 35.820007
    77.124023 37.855530
    44.308472 0.022888
    78.363037 13.533020
    21.279907 55.534363
    82.238770 26.612854
    25.106812 88.291931
    55.938721 0.532532
    10.476685 59.233093
    41.650391 33.729553
    7.077026 4.295349
    56.561279 99.641418
    19.595337 34.416199
    92.858887 46.705627
    27.719116 35.533142
    */
    
    //---------------------データファイル(data2_j.txt)------------
    /*
    都市の数 10 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 1 Y 1 最大試行回数 1000
    図示(0:しない,1:結果,2:初期状態と結果,3:ステップ) 3
    都市番号 0 図の大きさ(幅,高さ) 1000 750
    8.695068 2.771149
    8.235779 1.614838
    2.979126 3.795929
    2.749329 0.154266
    9.089355 8.873444
    4.010925 9.230804
    8.744507 5.347443
    2.489319 9.938202
    1.163330 8.061676
    6.153259 0.870209
    */
    			

  3. PHP

    <?php
    
    /****************************/
    /* 巡回セールスマン問題     */
    /* (分割法)               */
    /*      coded by Y.Suganuma */
    /****************************/
    
    /*************************/
    /* クラスPartitionの定義 */
    /*************************/
    class Partition {
    	private $city;   //都市の位置データ
    	private $city_i;   //都市の位置データ(作業領域)
    	private $p_x;   // x軸の分割点
    	private $p_y;   // y軸の分割点
    	private $rg;   // 都市間の距離
    	private $seed;   // 乱数の初期値
    	private $fix;   // =1 : 近傍を固定
                        // =0 : 近傍を可変
    	private $max_try;   // 最大試行回数
    	private $n_city;   // 都市の数
    	private $n_seq;   // 各領域の都市数
    	private $n_seq1;   // 各領域の都市数(ワーク)
    	private $n_p_x;   // x軸方向の分割数
    	private $n_p_y;   // y軸方向の分割数
    	private $seq;   // 経路
    	private $seq1;   // 経路(ワーク)
    	private $seq_w1;   // 作業領域
    	private $seq_w2;   // 作業領域
    	private $neib;   // 近傍(2 or 3)
    	private $seisu;   // 位置データの表現方法
                          //   =1 : 整数
                          //   =-1 : 実数(距離を整数計算)
                          //   =-2 : 実数(距離を実数計算)
    	private $sel;   // エッジの選択方法
                        //   =0 : 最良のものを選択
                        //   =1 : 最初のものを選択
    	private $state;   // 領域結合用ワーク
    	private $i_file;   // 入力ファイル名
    
    	public $Max;   // 最適経路の長さ
    	public $out_m;   // 出力方法
                         //   =-1 : ディスプレイ(経路長だけ)
                         //   =0 : ディスプレイ
                         //   =1 : ファイル
                         //   =2 : ファイル(経路長だけ)
    	public $o_file;   // 出力ファイル名
    
    	/**************************/
    	/* コンストラクタ         */
    	/*      name : ファイル名 */
    	/**************************/
    	function Partition($name)
    	{
    		$max = 0;
    						// ファイルのオープン
    		$this->i_file = $name;
    		$in           = fopen($name, "r");
    		if ($in == NULL)
    			exit("***error  データファイル名が不適当\n");
    						// 基本データ
    		fscanf($in, "%*s %d %*s %d %*s %d %*s %d", $this->n_city, $this->sel, $this->neib, $this->seisu);
    		fscanf($in, "%*s %d %*s %s", $this->out_m, $this->o_file);
        	fscanf($in, "%*s %*s %d %*s %d %*s %d", $this->n_p_x, $this->n_p_y, $this->max_try);
        
        	if ($this->neib < 0) {
    			$this->neib = -$this->neib;
        		$this->fix  = 0;
        	}
    		else
    			$this->fix = 1;
    						// 都市の位置データ
    		$this->city = array($this->n_city);
    		for ($i1 = 0; $i1 < $this->n_city; $i1++) {
        		$this->city[$i1] = array(2);
        		fscanf($in, "%f %f", $this->city[$i1][0], $this->city[$i1][1]);
        	}
        					// ファイルのクローズ
    		fclose($in);
    						// 距離テーブルの作成
    		$this->rg = array($this->n_city);
    	
    		for ($i1 = 0; $i1 < $this->n_city; $i1++) {
    			$this->rg[$i1] = array($this->n_city);
    			for ($i2 = $i1+1; $i2 < $this->n_city; $i2++) {
    				$x = $this->city[$i2][0] - $this->city[$i1][0];
    				$y = $this->city[$i2][1] - $this->city[$i1][1];
    				$this->rg[$i1][$i2] = sqrt($x * $x + $y * $y);
    				if ($this->seisu > -2)
    					$this->rg[$i1][$i2] = round($this->rg[$i1][$i2]);
    			}
    		}
        
    		for ($i1 = 1; $i1 < $this->n_city; $i1++) {
    			for ($i2 = 0; $i2 < $i1; $i2++)
    				$this->rg[$i1][$i2] = $this->rg[$i2][$i1];
    		}
    						// 作業領域
    		$this->state  = array($this->n_p_y);
    		$this->n_seq  = array($this->n_p_y);
    		$this->n_seq1 = array($this->n_p_y);
    		for ($i1 = 0; $i1 < $this->n_p_y; $i1++) {
    			$this->n_seq[$i1]  = array($this->n_p_x);
    			$this->n_seq1[$i1] = array($this->n_p_x);
    			$this->state[$i1]  = array($this->n_p_x);
        	}
        
        	$this->seq  = array($this->n_p_y);
    		$this->seq1 = array($this->n_p_y);
        	for ($i1 = 0; $i1 < $this->n_p_y; $i1++) {
        		$this->seq[$i1]  = array($this->n_p_x);
    			$this->seq1[$i1] = array($this->n_p_x);
    		}
    	
    		$this->seq_w1 = array($this->n_city);
    		$this->seq_w2 = array($this->n_city);
        	$this->p_x    = array($this->n_p_x);
        	$this->p_y    = array($this->n_p_y);
        					// 都市の分割
        	for ($i1 = 0; $i1 < $this->n_city; $i1++)
    			$this->seq_w1[$i1] = 0;
    	
    		$min_x = $this->city[0][0];
    		$max_x = $this->city[0][0];
    		$min_y = $this->city[0][1];
    		$max_y = $this->city[0][1];
    	
    		for ($i1 = 1; $i1 < $this->n_city; $i1++) {
    			if ($this->city[$i1][0] < $min_x)
    				$min_x = $this->city[$i1][0];
    			else {
    				if ($this->city[$i1][0] > $max_x)
    					$max_x = $this->city[$i1][0];
    			}
        		if ($this->city[$i1][1] < $min_y)
    				$min_y = $this->city[$i1][1];
    			else {
    				if ($this->city[$i1][1] > $max_y)
    					$max_y = $this->city[$i1][1];
    			}
    		}
    	
    		$s_x                       = ($max_x - $min_x) / $this->n_p_x;
    		$this->p_x[0]              = $min_x + $s_x;
    		$this->p_x[$this->n_p_x-1] = $max_x;
    		for ($i1 = 1; $i1 < $this->n_p_x-1; $i1++)
    			$this->p_x[$i1] = $this->p_x[0] + $i1 * $s_x;
        
        	$s_y                       = ($max_y - $min_y) / $this->n_p_y;
        	$this->p_y[0]              = $min_y + $s_y;
    		$this->p_y[$this->n_p_y-1] = $max_y;
        	for ($i1 = 1; $i1 < $this->n_p_y-1; $i1++)
        		$this->p_y[$i1] = $this->p_y[0] + $i1 * $s_y;
    	
    		for ($i1 = 0; $i1 < $this->n_p_y; $i1++) {
    			for ($i2 = 0; $i2 < $this->n_p_x; $i2++) {
    				$n = 0;
    				for ($i3 = 0; $i3 < $this->n_city; $i3++) {
        				if ($this->seq_w1[$i3] == 0) {
        					if ($this->city[$i3][0] <= $this->p_x[$i2] && $this->city[$i3][1] <= $this->p_y[$i1]) {
        						$this->seq_w1[$i3] = 1;
        						$this->seq_w2[$n]  = $i3;
    							$n++;
    						}
    					}
    				}
    				$this->n_seq1[$i1][$i2] = $n;
    				if ($n > 0) {
    					$this->seq[$i1][$i2]  = array($this->n_city);
    					$this->seq1[$i1][$i2] = array($this->n_city);
    					for ($i3 = 0; $i3 < $n; $i3++)
    						$this->seq1[$i1][$i2][$i3] = $this->seq_w2[$i3];
    					if ($n > $max)
    						$max = $n;
    				}
    			}
        	}
    						// 作業領域
    		printf("最大都市数 %d\n", $max);
    		$this->city_i = array($max);
    		for ($i1 = 0; $i1 < $max; $i1++)
    			$this->city_i[$i1] = array(2);
    	}
    	
    	/******************************/
        /* 最適化の実行               */
        /*      seed_i : 乱数の初期値 */
        /******************************/
        function Optimize($seed_i)
    	{
    		$r = 0;
    						// 初期設定
    		$this->seed = $seed_i;
    		mt_srand($seed_i);
    						// 分割数と開始時間の出力
    		if ($this->out_m > 0)
    			$this->Output(0, $r);
    	
    		for ($i1 = 0; $i1 < $this->n_p_y; $i1++) {
    			for ($i2 = 0; $i2 < $this->n_p_x; $i2++) {
    				$this->n_seq[$i1][$i2] = $this->n_seq1[$i1][$i2];
    				for ($i3 = 0; $i3 < $this->n_seq1[$i1][$i2]; $i3++)
        				$this->seq[$i1][$i2][$i3] = $this->seq1[$i1][$i2][$i3];
    			}
    		}
    						// 分割毎の最適化
    		for ($i1 = 0; $i1 < $this->n_p_y; $i1++) {
    			for ($i2 = 0; $i2 < $this->n_p_x; $i2++) {
    				if ($this->n_seq[$i1][$i2] > 3) {
    							// 近傍の大きさ
    					$nb = ($this->n_seq[$i1][$i2] > 3) ? $this->neib : 2;
    							// 都市位置データの設定
    					for ($i3 = 0; $i3 < $this->n_seq[$i1][$i2]; $i3++) {
    						$k                    = $this->seq[$i1][$i2][$i3];
    						$this->city_i[$i3][0] = $this->city[$k][0];
        					$this->city_i[$i3][1] = $this->city[$k][1];
        				}
        						// 最適化
    					$it  = new Iteration ($this->n_seq[$i1][$i2], $this->max_try, $this->seisu, $this->sel, $nb, $this->fix, 0, -1, 0, $this->o_file, $this->city_i);
        				$max = $it->Optimize();
    							// 結果の保存
    					for ($i3 = 0; $i3 < $this->n_seq[$i1][$i2]; $i3++) {
    						$k                 = $it->seq[$i3];
    						$this->seq_w1[$i3] = $this->seq[$i1][$i2][$k];
    					}
        				for ($i3 = 0; $i3 < $this->n_seq[$i1][$i2]; $i3++)
        					$this->seq[$i1][$i2][$i3] = $this->seq_w1[$i3];
        						// 出力
        				$r = ($this->seisu > -2) ? intval(kyori($this->n_seq[$i1][$i2], $this->seq[$i1][$i2], $this->rg)) : round((kyori($this->n_seq[$i1][$i2], $this->seq[$i1][$i2], $this->rg)));
    					printf("   y %d x %d $this->n_city %d range %d (trial %d)\n",
    	                       $i1+1, $i2+1, $this->n_seq[$i1][$i2], $r, $max);
    				}
    			}
    		}
    						// 経路の接続
    		$r = $this->Connect();
    						// 出力
    		$this->Output($this->n_city, $r);
    	}
    	
    	/***********************/
    	/* 出力                */
        /*      n_c : 都市の数 */
    	/*      r : 距離       */
    	/***********************/
    	function Output($n_c, $r)
    	{
    		$k = 0;
    	
    		if ($this->out_m <= 0) {
    			$out = STDOUT;
    			fwrite($out, "距離 ".$r."\n");
        		fgets(STDIN);
        	}
        	else {
    			$x   = getdate();
    			$now = $x["hours"]."時".$x["minutes"]."分".$x["seconds"]."秒";
        		$out = fopen($this->o_file, "ab");
    			if ($n_c > 0) {
    				printf("距離 %d\n", $r);
    				fwrite($out, "   距離 ".$r." 時間 ".$now."\n");
    			}
    			else
        			fwrite($out, "問題 ".$this->i_file." 乱数 ".$this->seed." 分割 ".$this->n_p_x." ".$this->n_p_y." 時間 ".$now."\n");
    		}
        
    		if ($n_c > 0 && ($this->out_m == 0 || $this->out_m == 1)) {
    			for ($i1 = 0; $i1 < $n_c; $i1++) {
    				$n = $this->seq_w1[$i1];
    				if ($this->seisu > 0)
    					fwrite($out, "  ".$n." ".intval($this->city[$n][0])." ".intval($this->city[$n][1])."\n");
    				else
    					fwrite($out, "  ".$n." ".$this->city[$n][0]." ".$this->city[$n][1]."\n");
    				if ($this->out_m == 0) {
    					$k++;
    					if ($k == 10) {
    						fgets(STDIN);
    						$k = 0;
    					}
    				}
        		}
    		}
    	
    		if ($this->out_m > 0)
    			fclose($out);
    	}
    	
    	/************************/
    	/* 分割された領域の接続 */
    	/************************/
    	function Connect()
    	{
    		$min   = 0;
        	$k1    = 0;
    		$k2    = 0;
    		$k3    = 0;
    		$k4    = 0;
    		$min_c = 0;
    		$r1    = 0;
    		$r2    = 0;
    		$r3    = 0;
    		$r4    = 0;
    		$s1    = 0;
    		$s2    = 0;
    		$sw    = 1;
        /*
    	     領域が1つの場合
        */
        	if ($this->n_p_x == 1 && $this->n_p_y == 1) {
    			for ($i1 = 0; $i1 < $this->n_seq[0][0]; $i1++)
    				$this->seq_w1[$i1] = $this->seq[0][0][$i1];
    		}
    	/*
    	     初期設定
        */
        	else {
        
        		for ($i1 = 0; $i1 < $this->n_p_y; $i1++) {
    				for ($i2 = 0; $i2 < $this->n_p_x; $i2++)
    					$this->state[$i1][$i2] = ($this->n_seq[$i1][$i2] > 0) ? 0 : 1;
    			}
    	/*
    	     実行
    	*/
    			while ($sw > 0) {
    						// 最小節点領域
    				$min_c = $this->n_city;
    				$sw    = 0;
    				for ($i1 = 0; $i1 < $this->n_p_y; $i1++) {
    					for ($i2 = 0; $i2 < $this->n_p_x; $i2++) {
    						if ($this->state[$i1][$i2] == 0 && $this->n_seq[$i1][$i2] < $min_c) {
    							$sw    = 1;
        						$r1    = $i1;
    							$r2    = $i2;
    							$min_c = $this->n_seq[$i1][$i2];
    						}
    					}
    				}
    						// 結合する対象領域の決定
    				if ($sw > 0) {
    					$sw = 0;
    					for ($i1 = 0; $i1 < $this->n_p_y; $i1++) {
    						for ($i2 = 0; $i2 < $this->n_p_x; $i2++) {
    							if ($this->state[$i1][$i2] == 0 && ($i1 != $r1 || $i2 != $r2)) {
    									// 節点の数>2
        							if ($this->n_seq[$r1][$r2] > 1) {
        								for ($i3 = 0; $i3 < $this->n_seq[$r1][$r2]; $i3++) {
        									$k1  = $this->seq[$r1][$r2][$i3];
    										$k2  = ($i3 == $this->n_seq[$r1][$r2]-1) ? $this->seq[$r1][$r2][0] : $this->seq[$r1][$r2][$i3+1];
        									$wd1 = $this->rg[$k1][$k2];
    										for ($i4 = 0; $i4 < $this->n_seq[$i1][$i2]; $i4++) {
    											$k3  = $this->seq[$i1][$i2][$i4];
    											$k4  = ($i4 == $this->n_seq[$i1][$i2]-1) ? $this->seq[$i1][$i2][0] : $this->seq[$i1][$i2][$i4+1];
    											$wd  = $wd1 + $this->rg[$k3][$k4];
        										$wa1 = $this->rg[$k1][$k3] + $this->rg[$k2][$k4];
        										$wa2 = $this->rg[$k1][$k4] + $this->rg[$k2][$k3];
        										if ($sw == 0 || $wa1-$wd < $min) {
        											$min = $wa1 - $wd;
    												$r3  = $i1;
    												$r4  = $i2;
    												$s1  = ($i3 == $this->n_seq[$r1][$r2]-1) ? 0 : $i3 + 1;
    												$s2  = ($i4 == $this->n_seq[$i1][$i2]-1) ? 0 : $i4 + 1;
    												$sw  = -1;
    											}
    											if ($sw == 0 || $wa2-$wd < $min) {
    												$min = $wa2 - $wd;
    												$r3  = $i1;
    												$r4  = $i2;
    												$s1  = $i3;
    												$s2  = ($i4 == $this->n_seq[$i1][$i2]-1) ? 0 : $i4 + 1;
    												$sw  = 1;
    											}
        									}
    									}
    								}
    									// 節点の数=1
    								else {
    									$k1 = $this->seq[$r1][$r2][0];
    									if ($this->n_seq[$i1][$i2] > 1) {
    										for ($i4 = 0; $i4 < $this->n_seq[$i1][$i2]; $i4++) {
    											$k3  = $this->seq[$i1][$i2][$i4];
    											$k4  = ($i4 == $this->n_seq[$i1][$i2]-1) ? $this->seq[$i1][$i2][0] : $this->seq[$i1][$i2][$i4+1];
    											$wd  = $this->rg[$k3][$k4];
    											$wa1 = $this->rg[$k1][$k3] + $this->rg[$k1][$k4];
        										if ($sw == 0 || $wa1-$wd < $min) {
        											$min = $wa1 - $wd;
        											$r3  = $i1;
    												$r4  = $i2;
        											$s1  = 0;
        											$s2  = ($i4 == $this->n_seq[$i1][$i2]-1) ? 0 : $i4 + 1;
    												$sw  = 1;
    											}
    										}
    									}
    									else {
        									$k3  = $this->seq[$i1][$i2][0];
        									$wa1 = $this->rg[$k1][$k3];
        									if ($sw == 0 || $wa1 < $min) {
        										$min = $wa1;
    											$r3  = $i1;
    											$r4  = $i2;
    											$s1  = 0;
    											$s2  = 0;
    											$sw  = 1;
    										}
    									}
    								}
    							}
    						}
    					}
    						// 領域の結合
    					$this->seq_w1[0] = $this->seq[$r1][$r2][$s1];
    					$k               = 1;
        				$n               = $s2;
    					for ($i1 = 0; $i1 < $this->n_seq[$r3][$r4]; $i1++) {
    						$this->seq_w1[$k] = $this->seq[$r3][$r4][$n];
    						$k++;
    						$n++;
    						if ($n > $this->n_seq[$r3][$r4]-1)
    							$n = 0;
    					}
    					if ($sw > 0) {
    						$n = $s1 + 1;
    						for ($i1 = 0; $i1 < $this->n_seq[$r1][$r2]-1; $i1++) {
    							if ($n > $this->n_seq[$r1][$r2]-1)
    								$n = 0;
        						$this->seq_w1[$k] = $this->seq[$r1][$r2][$n];
        						$k++;
        						$n++;
    						}
        				}
        				else {
    						$n = $s1 - 1;
    						for ($i1 = 0; $i1 < $this->n_seq[$r1][$r2]-1; $i1++) {
    							if ($n < 0)
    								$n = $this->n_seq[$r1][$r2] - 1;
    							$this->seq_w1[$k] = $this->seq[$r1][$r2][$n];
        						$k++;
        						$n--;
        					}
        				}
    						// 状態の変更
    					$this->n_seq[$r1][$r2] += $this->n_seq[$r3][$r4];
    					$this->state[$r3][$r4]  = 1;
    					for ($i1 = 0; $i1 < $this->n_seq[$r1][$r2]; $i1++)
    						$this->seq[$r1][$r2][$i1] = $this->seq_w1[$i1];
    					$sw  = 1;
    				}
    			}
    		}
    
    		$r         = ($this->seisu > -2) ? intval(kyori($this->n_city, $this->seq_w1, $this->rg)) : round(kyori($this->n_city, $this->seq_w1, $this->rg));
    		$this->Max = $r;
    
    		return $r;
    	}
    }
    
    /*************************/
    /* クラスIterationの定義 */
    /*************************/
    class Iteration {
    	private $city;   //都市の位置データ
    	private $rg;   // 都市間の距離
    	private $fix;   // =1 : 近傍を固定
                        // =0 : 近傍を可変
    	private $max_try;   // 最大試行回数
    	private $n_city;   // 都市の数
    	private $out_d;   // 表示間隔
    	private $seq_w1;   // 都市を訪れる順序(ワーク)
    	private $seq_w2;   // 都市を訪れる順序(ワーク)
    	private $seq_w3;   // 都市を訪れる順序(ワーク)
    	private $seq_w4;   // 都市を訪れる順序(ワーク)
    	private $seq_w5;   // 都市を訪れる順序(ワーク)
    	private $neib;   // 近傍(2 or 3)
    	private $out_lvl;   // 出力レベル
                            //   =0 : 最終出力だけ
                            //   n>0 : n世代毎に出力(負の時はファイル)
    	private $out_m;   // 出力方法
                          //   =-1 : 出力しない
                          //   =0 : すべてを出力
                          //   =1 : 評価値だけを出力(最終結果だけはすべてを出力)
    	private $seisu;   // 位置データの表現方法
                          //   =1 : 整数
                          //   =-1 : 実数(距離を整数計算)
                          //   =-2 : 実数(距離を実数計算)
    	private $sel;   // エッジの選択方法
                        //   =0 : 最良のものを選択
                        //   =1 : 最初のものを選択
    	private $o_file;   // 出力ファイル名
    
    	public $seq;   // 都市を訪れる順序
    
    	/**********************************/
    	/* コンストラクタ                 */
    	/*      n_city_i : 都市の数       */
        /*      max_try_i : 最大試行回数  */
    	/*      sei_i : 整数 or 実数      */
    	/*      sel_i : エッジの選択方法  */
    	/*      neib_i : 近傍             */
    	/*      fix_i : 近傍の扱い方      */
    	/*      out_lvl_i : 出力レベル    */
    	/*      out_m_i : 出力方法        */
    	/*      out_d_i : 表示間隔        */
    	/*      o_file_i : 出力ファイル名 */
    	/*      city_i : 都市の位置データ */
    	/**********************************/
        function Iteration ($n_city_i, $max_tri_i, $sei_i, $sel_i, $neib_i, $fix_i, $out_lvl_i, $out_m_i, $out_d_i, $o_file_i, $city_i)
    	{
        					// 値の設定
    		$this->n_city  = $n_city_i;
        	$this->max_try = $max_tri_i;
        	$this->seisu   = $sei_i;
        	$this->sel     = $sel_i;
    		$this->neib    = $neib_i;
        	$this->fix     = $fix_i;
        	$this->out_lvl = $out_lvl_i;
    		$this->out_m   = $out_m_i;
    		$this->out_d   = $out_d_i;
    		$this->o_file  = $o_file_i;
    						// 都市の位置データ
    		$this->city = array($this->n_city);
    		for ($i1 = 0; $i1 < $this->n_city; $i1++) {
    			$this->city[$i1]    = array(2);
    			$this->city[$i1][0] = $city_i[$i1][0];
    			$this->city[$i1][1] = $city_i[$i1][1];
    		}
        					// 距離テーブルの作成
    		$this->rg = array($this->n_city);
    	
    		for ($i1 = 0; $i1 < $this->n_city; $i1++) {
    			$this->rg[$i1] = array($this->n_city);
    			for ($i2 = $i1+1; $i2 < $this->n_city; $i2++) {
    				$x = $this->city[$i2][0] - $this->city[$i1][0];
    				$y = $this->city[$i2][1] - $this->city[$i1][1];
    				$this->rg[$i1][$i2] = sqrt($x * $x + $y * $y);
    				if ($this->seisu > -2)
    					$this->rg[$i1][$i2] = round($this->rg[$i1][$i2]);
        		}
        	}
    	
        	for ($i1 = 1; $i1 < $this->n_city; $i1++) {
        		for ($i2 = 0; $i2 < $i1; $i2++)
        			$this->rg[$i1][$i2] = $this->rg[$i2][$i1];
    		}
        					// 都市を訪れる順序(初期設定)
        	$this->seq    = array($this->n_city);
        	$this->seq_w1 = array($this->n_city);
    		$this->seq_w2 = array($this->n_city);
        	$this->seq_w3 = array($this->n_city);
        	$this->seq_w4 = array($this->n_city);
    		$this->seq_w5 = array($this->n_city);
    	
    		for ($i1 = 0; $i1 < $this->n_city; $i1++) {
    			$sw = 0;
    			while ($sw == 0) {
    				$ct = intval((mt_rand() / mt_getrandmax()) * $this->n_city);
    				if ($ct >= $this->n_city)
    					$ct = $this->n_city - 1;
    				$this->seq[$i1] = $ct;
    				$sw      = 1;
    				for ($i2 = 0; $i2 < $i1 && $sw > 0; $i2++) {
        				if ($ct == $this->seq[$i2])
    						$sw = 0;
    				}
    			}
    		}
    	}
    	
    	/****************/
    	/* 最適化の実行 */
    	/****************/
        function Optimize()
    	{
    						// 初期設定
    		$n_tri = 0;
    		$max   = kyori($this->n_city, $this->seq, $this->rg);
    	
    		if ($this->out_m >= 0 && abs($this->out_lvl) > 0) {
    			if ($this->seisu > -2)
    				printf("***試行回数 %d 距離 %d\n", $n_tri, intval($max));
        		else
        			printf("***試行回数 %d 距離 %f\n", $n_tri, $max);
    			$this->Output($this->out_lvl, $n_tri, $max);
        	}
        					// 実行
        	$sw = 1;
    		for ($n_tri = 1; $n_tri <= $this->max_try && $sw > 0; $n_tri++) {
        						// 改善
        		$sw = $this->Change($max);
        						// 出力
    			if ($this->out_d > 0 && $n_tri%$this->out_d == 0) {
        			if ($this->seisu > -2)
        				printf("***試行回数 %d 距離 %d\n", $n_tri, intval($max));
    				else
    					printf("***試行回数 %d 距離 %f\n", $n_tri, $max);
    			}
    	
    			if ($this->out_m >= 0 && abs($this->out_lvl) > 0) {
    				if ($n_tri%abs($this->out_lvl) == 0)
    					$this->Output($this->out_lvl, $n_tri, $max);
    			}
    		}
    						// 最終出力
    		if ($this->out_m >= 0) {
        		$n_tri--;
    			if ($this->seisu > -2)
    				printf("***試行回数 %d 距離 %d\n", $n_tri, intval($max));
    			else
    				printf("***試行回数 %d 距離 %f\n", $n_tri, $max);
    			$this->Output($this->out_lvl, $n_tri, $max);
    		}
    	
    		return $n_tri;
    	}
    	
        /*******************************/
        /* 出力                        */
    	/*      sw : >=0 : 出力先未定  */
        /*           < 0 : ファイル    */
        /*      n_tri : 現在の試行回数 */
        /*      r : 距離               */
    	/*******************************/
        function Output($sw, $n_tri, $r)
        {
        	$k = 0;
    	
    		if ($sw >= 0) {
    			printf("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			scanf(STDIN, "%d", $pr);
    		}
    		else
    			$pr = -1;
    	
    		if ($pr != 0) {
    	
    			if ($pr > 0) {
        			$out = STDOUT;
    				fgets(STDIN);
    			}
    			else {
    				$x   = getdate();
    				$now = $x["hours"]."時".$x["minutes"]."分".$x["seconds"]."秒";
    				$out = fopen($this->o_file, "ab");
    				if ($this->seisu > -2)
    					fwrite($out, "***試行回数 ".$n_tri." 距離 ".intval($r)." 時間 ".$now."\n");
    				else
    					fwrite($out, "***試行回数 ".$n_tri." 距離 ".round($r)." 時間 ".$now."\n");
        		}
        
    			if ($this->out_m == 0) {
        			for ($i1 = 0; $i1 < $this->n_city; $i1++) {
        				$n = $this->seq[$i1];
        				if ($this->seisu > 0)
    						fwrite($out, "  ".$n." ".intval($this->city[$n][0])." ".intval($this->city[$n][1])."\n");
        				else
        					fwrite($out, "  ".$n." ".$this->city[$n][0]." ".$this->city[$n][1]."\n");
        				if ($pr > 0) {
    						$k++;
        					if ($k == $pr) {
        						fgets(STDIN);
    							$k = 0;
    						}
    					}
    				}
    			}
    	
    			if ($pr <= 0)
    				fclose($out);
    		}
    	}
    	
        /**************************************/
    	/* エッジの入れ替え                   */
    	/*      r_m : 距離                    */
    	/*      return : =0 : 改善がなかった  */
    	/*               =1 : 改善があった    */
    	/**************************************/
    	function Change(&$r_m)
    	{
    		$max1 = 0.0;
    		$ch   = 0;
    		$k1   = 0;
    		$k2   = 0;
    		$n1   = 0;
    		$n2   = 0;
    		$sw   = 0;
    		$sw1  = 0;
        
        	$max  = $r_m;
    	
        /*
             近傍を可変
        */
    		if ($this->fix == 0) {
        					// 初期設定(k=2)
        		$k = 2;
        		for ($i1 = 0; $i1 < $this->n_city; $i1++) {
    				$this->seq_w4[$i1] = $this->seq[$i1];
        			$this->seq_w3[$i1] = 0;
        		}
    							// 評価
    			$sw2 = 0;
    			for ($i0 = 0; $i0 < $this->n_city-2 && $sw2 < 2; $i0++) {
    	
    				$n = ($i0 == 0) ? $this->n_city-1 : $this->n_city;
    	
    				for ($i1 = $i0+2; $i1 < $n && $sw2 < 2; $i1++) {
    								// 相手の場所
    					$k3 = $i1;
    					$k4 = $k3 + 1;
    					if ($k4 > $this->n_city-1)
        					$k4 = 0;
    								// 順番の入れ替え
    					$n3 = -1;
    					for ($i2 = 0; $i2 < $this->n_city && $n3 < 0; $i2++) {
    						if ($this->seq_w4[$i2] == $this->seq[$i0+1])
    							$n3 = $i2 + 1;
    					}
    					$nn = $n3;
    					$n4 = -1;
    					for ($i2 = 0; $i2 < $this->n_city && $n4 < 0; $i2++) {
    						if ($nn > $this->n_city-1)
        						$nn = 0;
        					if ($this->seq_w4[$nn] == $this->seq[$k3] || $this->seq_w4[$nn] == $this->seq[$k4])
    							$n4 = $this->seq_w4[$nn];
        					else
        						$nn++;
        				}
    					if ($n4 == $this->seq[$k4]) {
        					$n4 = $k3;
        					$k3 = $k4;
        					$k4 = $n4;
    					}
        							// 評価
        				$this->seq_w1[0] = $this->seq[$k4];
    					$this->seq_w1[1] = $this->seq[$i0+1];
    					$n4              = -1;
    					$nn              = 2;
    					while ($n4 < 0) {
    						if ($n3 > $this->n_city-1)
    							$n3 = 0;
    						$this->seq_w1[$nn] = $this->seq_w4[$n3];
    						if ($this->seq_w4[$n3] == $this->seq[$k3])
    							$n4 = 1;
    						$nn++;
    						$n3++;
        				}
    					$this->seq_w1[$nn] = $this->seq[$i0];
    					$nn++;
    					$n3 = -1;
    					$n4 = -1;
    					for ($i2 = 0; $i2 < $this->n_city && $n3 < 0; $i2++) {
    						if ($this->seq_w4[$i2] == $this->seq[$i0]) {
    							$n3 = $i2 - 1;
    							if ($n3 < 0)
    								$n3 = $this->n_city - 1;
    						}
        				}
        				while ($n4 < 0) {
    						if ($this->seq_w4[$n3] == $this->seq[$k4])
        						$n4 = 1;
        					else {
        						$this->seq_w1[$nn] = $this->seq_w4[$n3];
    							$nn++;
        						$n3--;
        						if ($n3 < 0)
        							$n3 = $this->n_city - 1;
    						}
        				}
        
    					$r = kyori($this->n_city, $this->seq_w1, $this->rg);
    								// 最適値の保存
    					if ($sw2 == 0 || $r < $max1) {
    						$sw2  = 1;
    						$max1 = $r;
    						$n1   = $k3;
    						$n2   = $k4;
    						$k1   = $i0;
    						$k2   = $i0 + 1;
    						for ($i2 = 0; $i2 < $this->n_city; $i2++)
    							$this->seq_w5[$i2] = $this->seq_w1[$i2];
        					if ($this->sel > 0 && $max1 < $max)
    							$sw2 = 2;
    					}
    				}
    			}
    							// 最適値の保存と近傍の増加
    			if ($sw2 > 0) {
    				if ($max1 < $max) {
    					$sw  = 1;
    					$max = $max1;
    					for ($i1 = 0; $i1 < $this->n_city; $i1++)
        					$this->seq_w2[$i1] = $this->seq_w5[$i1];
        			}
    				if ($k < $this->neib) {
        				for ($i1 = 0; $i1 < $this->n_city; $i1++)
        					$this->seq_w4[$i1] = $this->seq_w5[$i1];
        				$this->seq_w3[$k1] = 1;
    					$this->seq_w3[$k2] = 1;
        				$this->seq_w3[$n1] = 1;
        				$this->seq_w3[$n2] = 1;
        				$k1                = $n2;
    					$k++;
        			}
        			else
    					$sw1 = 1;
    			}
    			else
    				$sw1 = 1;
    						// 実行(k>2)
    			while ($sw1 == 0) {
    							// 評価
    				$sw2 = 0;
    				for ($i1 = 0; $i1 < $this->n_city; $i1++) {
    								// 相手の場所
    					$k3 = $i1;
        				$k4 = $k3 + 1;
    					if ($k4 > $this->n_city-1)
    						$k4 = 0;
    	
    					if ($this->seq_w3[$k3] == 0 && $this->seq_w3[$k4] == 0) {
    								// 順番の入れ替え
    						$n3 = -1;
    						for ($i2 = 0; $i2 < $this->n_city && $n3 < 0; $i2++) {
    							if ($this->seq_w4[$i2] == $this->seq[$k2])
    								$n3 = $i2 + 1;
    						}
        					$nn = $n3;
        					$n4 = -1;
    						for ($i2 = 0; $i2 < $this->n_city && $n4 < 0; $i2++) {
        						if ($nn > $this->n_city-1)
        							$nn = 0;
        						if ($this->seq_w4[$nn] == $this->seq[$k3] || $this->seq_w4[$nn] == $this->seq[$k4])
    								$n4 = $this->seq_w4[$nn];
        						else
        							$nn++;
        					}
    						if ($n4 == $this->seq[$k4]) {
        						$n4 = $k3;
        						$k3 = $k4;
    							$k4 = $n4;
    						}
    								// 評価
    						$this->seq_w1[0] = $this->seq[$k4];
    						$this->seq_w1[1] = $this->seq[$k2];
    						$n4              = -1;
    						$nn              = 2;
    						while ($n4 < 0) {
    							if ($n3 > $this->n_city-1)
    								$n3 = 0;
    							$this->seq_w1[$nn] = $this->seq_w4[$n3];
        						if ($this->seq_w4[$n3] == $this->seq[$k3])
    								$n4 = 1;
    							$nn++;
    							$n3++;
    						}
    						$this->seq_w1[$nn] = $this->seq[$k1];
    						$nn++;
    						$n3 = -1;
    						$n4 = -1;
    						for ($i2 = 0; $i2 < $this->n_city && $n3 < 0; $i2++) {
    							if ($this->seq_w4[$i2] == $this->seq[$k1]) {
        							$n3 = $i2 - 1;
        							if ($n3 < 0)
    									$n3 = $this->n_city - 1;
        						}
        					}
        					while ($n4 < 0) {
    							if ($this->seq_w4[$n3] == $this->seq[$k4])
        							$n4 = 1;
        						else {
        							$this->seq_w1[$nn] = $this->seq_w4[$n3];
    								$nn++;
        							$n3--;
        							if ($n3 < 0)
    									$n3 = $this->n_city - 1;
    							}
    						}
    	
    						$r = kyori($this->n_city, $this->seq_w1, $this->rg);
    								// 最適値の保存
    						if ($sw2 == 0 || $r < $max1) {
    							$sw2  = 1;
    							$max1 = $r;
    							$n1   = $k3;
    							$n2   = $k4;
        						for ($i2 = 0; $i2 < $this->n_city; $i2++)
    								$this->seq_w5[$i2] = $this->seq_w1[$i2];
    						}
    					}
    				}
    							// 最適値の保存と近傍の増加
    				if ($sw2 > 0) {
    					if ($max1 < $max) {
    						$sw  = 1;
    						$max = $max1;
    						for ($i1 = 0; $i1 < $this->n_city; $i1++)
        						$this->seq_w2[$i1] = $this->seq_w5[$i1];
        				}
    					if ($k < $this->neib) {
        					for ($i1 = 0; $i1 < $this->n_city; $i1++)
        						$this->seq_w4[$i1] = $this->seq_w5[$i1];
        					$this->seq_w3[$n1] = 1;
    						$this->seq_w3[$n2] = 1;
        					$k1         = $n2;
        					$k++;
        				}
    					else
        					$sw1 = 1;
        			}
    				else
    					$sw1 = 1;
    			}
    		}
    	/*
    	     近傍を固定
    	*/
    		else {
    			$n3  = intval((mt_rand() / mt_getrandmax()) * ($this->n_city - 2));
    			if ($n3 > $this->n_city-3)
    				$n3 = $this->n_city - 3;
                                 // 2近傍
    			for ($i1 = 0; $i1 <= $this->n_city-3 && $ch == 0; $i1++) {
    	
    				if ($n3 == 0)
    					$n1 = $this->n_city - 2;
    				else
    					$n1 = $this->n_city - 1;
    	
    				for ($i2 = $n3+2; $i2 <= $n1 && $ch == 0; $i2++) {
    	                              // 枝の場所((n3,n3+1), (k1,k2))
    					$k1 = $i2;
        				if ($i2 == $this->n_city-1)
        					$k2 = 0;
    					else
        					$k2 = $i2 + 1;
                                      // 枝の入れ替え
        				$this->seq_w1[0] = $this->seq[$n3];
    					$k         = 1;
        				for ($i3 = $k1; $i3 >= $n3+1; $i3--) {
        					$this->seq_w1[$k] = $this->seq[$i3];
        					$k++;
    					}
        
        				$nn = $k2;
    					while ($nn != $n3) {
    						$this->seq_w1[$k] = $this->seq[$nn];
    						$k++;
    						$nn++;
    						if ($nn > $this->n_city-1)
    							$nn = 0;
    					}
    	                              // 評価
    					$r = kyori($this->n_city, $this->seq_w1, $this->rg);
    	
    					if ($r < $max) {
        					$max = $r;
    						$sw  = 1;
    						for ($i3 = 0; $i3 < $this->n_city; $i3++)
    							$this->seq_w2[$i3] = $this->seq_w1[$i3];
    						if ($this->sel > 0)
    							$ch = 1;
    					}
    				}
    	
    				$n3++;
    				if ($n3 > $this->n_city-3)
        				$n3 = 0;
        		}
    	                         // 3近傍
        		if ($this->neib == 3 && $ch == 0) {
        
        			for ($i1 = 0; $i1 <= $this->n_city-3 && $ch == 0; $i1++) {
    	
        				$n1 = $this->n_city - 2;
        				$n2 = $this->n_city - 1;
        
    					for ($i2 = $n3+1; $i2 <= $n1 && $ch == 0; $i2++) {
        
        					for ($i3 = $i2+1; $i3 <= $n2 && $ch == 0; $i3++) {
    	                              // 枝の場所((n3,n3+1), ($i2,$i2+1), (k1,k2))
    							$k1 = $i3;
    							if ($i3 == $this->n_city-1)
    								$k2 = 0;
    							else
    								$k2 = $i3 + 1;
    	                              // 枝の入れ替えと評価
    	                                   // 入れ替え(その1)
    							$this->seq_w1[0] = $this->seq[$n3];
    							$k         = 1;
    							for ($i4 = $i2; $i4 >= $n3+1; $i4--) {
        							$this->seq_w1[$k] = $this->seq[$i4];
    								$k++;
    							}
    	
    							for ($i4 = $k1; $i4 >= $i2+1; $i4--) {
    								$this->seq_w1[$k] = $this->seq[$i4];
    								$k++;
    							}
    	
    							$nn = $k2;
    							while ($nn != $n3) {
        							$this->seq_w1[$k] = $this->seq[$nn];
        							$k++;
    								$nn++;
        							if ($nn > $this->n_city-1)
        								$nn = 0;
        						}
    	                                   // 評価(その1)
        						$r = kyori($this->n_city, $this->seq_w1, $this->rg);
        
        						if ($r < $max) {
    								$max = $r;
        							$sw  = 1;
        							for ($i3 = 0; $i3 < $this->n_city; $i3++)
    									$this->seq_w2[$i3] = $this->seq_w1[$i3];
    								if ($this->sel > 0)
    									$ch = 1;
    							}
    	                                   // 入れ替え(その2)
    							$this->seq_w1[0] = $this->seq[$n3];
    							$k         = 1;
    							for ($i4 = $k1; $i4 >= $i2+1; $i4--) {
    								$this->seq_w1[$k] = $this->seq[$i4];
    								$k++;
    							}
        
    							for ($i4 = $n3+1; $i4 <= $i2; $i4++) {
    								$this->seq_w1[$k] = $this->seq[$i4];
    								$k++;
    							}
    	
    							$nn = $k2;
    							while ($nn != $n3) {
    								$this->seq_w1[$k] = $this->seq[$nn];
    								$k++;
    								$nn++;
        							if ($nn > $this->n_city-1)
        								$nn = 0;
    							}
                                           // 評価(その2)
        						$r = kyori($this->n_city, $this->seq_w1, $this->rg);
        
    							if ($r < $max) {
        							$max = $r;
        							$sw  = 1;
        							for ($i3 = 0; $i3 < $this->n_city; $i3++)
    									$this->seq_w2[$i3] = $this->seq_w1[$i3];
        							if ($this->sel > 0)
        								$ch = 1;
    							}
    	                                   // 入れ替え(その3)
    							$this->seq_w1[0] = $this->seq[$n3];
    							$k         = 1;
    							for ($i4 = $i2+1; $i4 <= $k1; $i4++) {
    								$this->seq_w1[$k] = $this->seq[$i4];
    								$k++;
    							}
    	
    							for ($i4 = $i2; $i4 >= $n3+1; $i4--) {
    								$this->seq_w1[$k] = $this->seq[$i4];
        							$k++;
    							}
    	
    							$nn = $k2;
    							while ($nn != $n3) {
    								$this->seq_w1[$k] = $this->seq[$nn];
    								$k++;
    								$nn++;
    								if ($nn > $this->n_city-1)
    									$nn = 0;
    							}
                                           // 評価(その3)
        						$r = kyori($this->n_city, $this->seq_w1, $this->rg);
    	
        						if ($r < $max) {
        							$max = $r;
        							$sw  = 1;
    								for ($i3 = 0; $i3 < $this->n_city; $i3++)
        								$this->seq_w2[$i3] = $this->seq_w1[$i3];
        							if ($this->sel > 0)
        								$ch = 1;
    							}
                                           // 入れ替え(その4)
        						$this->seq_w1[0] = $this->seq[$n3];
    							$k               = 1;
    							for ($i4 = $i2+1; $i4 <= $k1; $i4++) {
    								$this->seq_w1[$k] = $this->seq[$i4];
    								$k++;
    							}
    	
    							for ($i4 = $n3+1; $i4 <= $i2; $i4++) {
    								$this->seq_w1[$k] = $this->seq[$i4];
    								$k++;
    							}
    	
        						$nn = $k2;
    							while ($nn != $n3) {
    								$this->seq_w1[$k] = $this->seq[$nn];
    								$k++;
    								$nn++;
    								if ($nn > $this->n_city-1)
    									$nn = 0;
    							}
    	                                   // 評価(その4)
    							$r = kyori($this->n_city, $this->seq_w1, $this->rg);
    	
        						if ($r < $max) {
        							$max = $r;
    								$sw  = 1;
        							for ($i3 = 0; $i3 < $this->n_city; $i3++)
        								$this->seq_w2[$i3] = $this->seq_w1[$i3];
        							if ($this->sel > 0)
    									$ch = 1;
        						}
        					}
        				}
    	
        				$n3++;
        				if ($n3 > $this->n_city-3)
    						$n3 = 0;
    				}
    			}
    		}
    	                         // 設定
    		if ($sw > 0) {
    			$r_m = $max;
    			for ($i1 = 0; $i1 < $this->n_city; $i1++)
    				$this->seq[$i1] = $this->seq_w2[$i1];
    		}
    	
    		return $sw;
    	}
    }
    
    /*********************************/
    /* 距離の計算                    */
    /*      n_c : 都市の数           */
    /*      p : 都市番号             */
    /*      rg : 都市間の距離        */
    /*      return : 距離            */
    /*********************************/
    function kyori($n_c, $p, $rg)
    {
    	$range = 0;
    	$n1    = $p[0];
    
    	for ($i1 = 1; $i1 < $n_c; $i1++) {
    		$n2     = $p[$i1];
    		$range += $rg[$n1][$n2];
    		$n1     = $n2;
    	}
    
    	$n2     = $p[0];
    	$range += $rg[$n1][$n2];
    
    	return $range;
    }
    
    /****************/
    /* main program */
    /****************/
    					// 入力ミス
    	if (count($argv) <= 1)
    		exit("***error  ファイル名を入力して下さい\n");
    					// 入力OK
    	else {
    						// ファイルのオープン
    		$in = fopen($argv[1], "rb");
    		if ($in == NULL)
    			exit("***error  ファイル名が不適当です\n");
    						// 入力データファイル名と問題数
    		fscanf($in, "%*s %d", $nm);
    
    		for ($i0 = 0; $i0 < $nm; $i0++) {
    							// 各問題の実行
    			fscanf($in, "%*s %s %*s %d", $i_file, $n);
    			$pt   = new Partition($i_file);
    			$mean = 0.0;
    			$max  = -1;
    								// 乱数の初期値を変える
    			for ($i1 = 0; $i1 < $n; $i1++) {
    									// 問題
    				printf("\n+++++問題 %s +++++\n", $i_file);
    									// 最適化
    				$pt->Optimize(1000 * $i1 + 1234567);   // 引数は乱数の初期値
    									// 最適値とその平均の計算
    				$mean += $pt->Max;
    				if ($max < 0 || $pt->Max < $max)
    					$max = $pt->Max;
    			}
    							// 結果
    			if ($pt->out_m <= 0)
    				printf("     -----最小 %d 平均 %f-----\n", $max, $mean/$n);
    			else {
    				$out = fopen($pt->o_file, "ab");
    				$str = sprintf("     -----最小 %d 平均 %f-----\n", $max, $mean/$n);
    				fwrite($out, $str);
    				fclose($out);
    			}
    		}
    
    		fclose($in);
    	}
    
    //------------------------ケーススタディデータ(data.txt)------
    /*
    問題の数 2
    問題 data1.txt 繰り返し回数 2
    問題 data2.txt 繰り返し回数 1
    */
    //---------------------データファイル(data1.txt)------------
    /*
    都市の数 50 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 2 Y 2 最大試行回数 1000
    86.950684 27.711487
    82.357788 16.148376
    29.791260 37.959290
    27.493286 1.542664
    90.893555 88.734436
    40.109253 92.308044
    87.445068 53.474426
    24.893188 99.382019
    11.633301 80.616760
    61.532593 8.702087
    30.645752 93.598938
    4.714966 81.205750
    86.669922 90.858459
    84.127808 52.830505
    96.893311 45.832825
    4.458618 34.513855
    53.503418 6.959534
    45.394897 12.193298
    23.687744 97.676086
    61.624146 46.806335
    49.633789 16.419983
    82.833862 74.290466
    48.529053 36.628723
    13.711548 5.583191
    12.561035 6.739807
    33.944702 26.622009
    8.917236 50.190735
    98.220825 98.344421
    79.785156 65.419006
    36.227417 56.687927
    42.352295 25.862122
    52.651978 12.590027
    88.806152 79.957581
    27.182007 51.988220
    86.334229 51.142883
    14.505005 35.820007
    77.124023 37.855530
    44.308472 0.022888
    78.363037 13.533020
    21.279907 55.534363
    82.238770 26.612854
    25.106812 88.291931
    55.938721 0.532532
    10.476685 59.233093
    41.650391 33.729553
    7.077026 4.295349
    56.561279 99.641418
    19.595337 34.416199
    92.858887 46.705627
    27.719116 35.533142
    */
    
    //---------------------データファイル(data2.txt)------------
    /*
    都市の数 10 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 1 Y 1 最大試行回数 1000
    8.695068 2.771149
    8.235779 1.614838
    2.979126 3.795929
    2.749329 0.154266
    9.089355 8.873444
    4.010925 9.230804
    8.744507 5.347443
    2.489319 9.938202
    1.163330 8.061676
    6.153259 0.870209
    */
    
    ?>
    			

  4. Ruby

    ################################
    # 巡回セールスマン問題(分割法)
    #      coded by Y.Suganuma
    ################################
    
    #################################
    # 距離の計算
    #      n_c : 都市の数
    #      p : 都市番号
    #      rg : 都市間の距離
    #      return : 距離
    #################################
    
    def kyori(n_c, p, rg)
    
    	r  = 0.0
    	n1 = p[0]
    
    	for i1 in 1 ... n_c
    		n2  = p[i1]
    		r  += rg[n1][n2]
    		n1  = n2
    	end
    
    	n2  = p[0]
    	r  += rg[n1][n2]
    
    	return r
    end
    
    #########################
    # クラスIterationの定義
    #########################
    
    class Iteration
    	
    	###################################
    	# コンストラクタ
    	#      n_city_i 都市の数
    	#      max_try_i 最大試行回数
    	#      sei_i 整数 or 実数
    	#      sel_i エッジの選択方法
    	#      neib_i 近傍
    	#      fix_i 近傍の扱い方
    	#      out_lvl_i 出力レベル
    	#      out_m_i 出力方法
    	#      out_d_i 表示間隔
    	#      o_file_i 出力ファイル名
    	#      city_i 都市の位置データ
    	###################################
    
    	def initialize(n_city_i, max_tri_i, sei_i, sel_i, neib_i, fix_i, out_lvl_i, out_m_i, out_d_i, o_file_i, city_i)
    						# 値の設定
    		@_n_city  = n_city_i   # 都市の数
    		@_max_try = max_tri_i   # 最大試行回数
    		@_seisu   = sei_i   # 位置データの表現方法
    		                    #   =1 整数
    		                    #   =-1 実数(距離を整数計算)
    		                    #   =-2 実数(距離を実数計算)
    		@_sel     = sel_i   # エッジの選択方法
    		                    #   =0 最良のものを選択
    		                    #   =1 最初のものを選択
    		@_neib    = neib_i   # 近傍(2 or 3)
    		@_fix     = fix_i   # =1 近傍を固定
    		                    # =0 近傍を可変
    		@_out_lvl = out_lvl_i   # 出力レベル
    		                        #   =0 最終出力だけ
    		                        #   n>0 n世代毎に出力(負の時はファイル)
    		@_out_m   = out_m_i   # 出力方法
    		                      #   =-1 出力しない
    		                      #   =0 すべてを出力
    		                      #   =1 評価値だけを出力(最終結果だけはすべてを出力)
    		@_out_d   = out_d_i   # 表示間隔
    		@_o_file  = o_file_i   # 出力ファイル名
    		@_city    = city_i   # 都市の位置データ
    						# 距離テーブルの作成
    		@_rg = Array.new(@_n_city)
    		for i1 in 0 ... @_n_city
    			@_rg[i1] = Array.new(@_n_city)
    		end
    	
    		for i1 in 0 ... @_n_city-1
    			for i2 in i1+1 ... @_n_city
    				x = @_city[i2][0] - @_city[i1][0]
    				y = @_city[i2][1] - @_city[i1][1]
    				@_rg[i1][i2] = Math.sqrt(x * x + y * y)
    				if @_seisu > -2
    					@_rg[i1][i2] = @_rg[i1][i2].round()
    				end
    			end
    		end
    	
    		for i1 in 1 ... @_n_city
    			for i2 in 0 ... i1
    				@_rg[i1][i2] = @_rg[i2][i1]
    			end
    		end
    						# 都市を訪れる順序(初期設定)
    		@_seq    = Array.new(@_n_city)
    		@_seq_w1 = Array.new(@_n_city)
    		@_seq_w2 = Array.new(@_n_city)
    		@_seq_w3 = Array.new(@_n_city)
    		@_seq_w4 = Array.new(@_n_city)
    		@_seq_w5 = Array.new(@_n_city)
    	
    		for i1 in 0 ... @_n_city
    			sw = 0
    			while sw == 0
    				ct = Integer(rand(0) * @_n_city)
    				if ct >= @_n_city
    					ct = @_n_city - 1
    				end
    				@_seq[i1] = ct
    				sw        = 1
    				for i2 in 0 ... i1
    					if ct == @_seq[i2]
    						sw = 0
    						break
    					end
    				end
    			end
    		end
    	end
    
    	################
    	# 最適化の実行
    	################
    
    	def Optimize ()
    						# 初期設定
    		n_tri  = 0
    		max    = Array.new(1)
    		max[0] = kyori(@_n_city, @_seq, @_rg)
    	
    		if @_out_m >= 0 && @_out_lvl.abs() > 0
    			if @_seisu > -2
    				print("***試行回数 " + String(n_tri) + " 距離 " + String(Integer(max[0])) + "\n")
    			else
    				print("***試行回数 " + String(n_tri) + " 距離 " + String(max[0]) + "\n")
    			end
    			Output(@_out_lvl, n_tri, max[0])
    		end
    						# 実行
    		sw = 1
    		for n_tri in 1 ... @_max_try+1
    							# 改善
    			sw = Change(max)
    							# 出力
    			if @_out_d > 0 and n_tri%@_out_d == 0
    				if @_seisu > -2
    					print("***試行回数 " + String(n_tri) + " 距離 " + String(Integer(max[0])) + "\n")
    				else
    					print("***試行回数 " + String(n_tri) + " 距離 " + String(max[0]) + "\n")
    				end
    			end
    	
    			if @_out_m >= 0 && @_out_lvl.abs() > 0
    				if n_tri%@_out_lvl.abs() == 0
    					Output(@_out_lvl, n_tri, max[0])
    				end
    			end
    			if sw <= 0
    				break
    			end
    		end
    						# 最終出力
    		if @_out_m >= 0
    			n_tri -= 1
    			if @_seisu > -2
    				print("***試行回数 " + String(n_tri) + " 距離 " + String(Integer(max[0])) + "\n")
    			else
    				print("***試行回数 " + String(n_tri) + " 距離 " + String(max[0]) + "\n")
    			end
    			Output(@_out_lvl, n_tri, max[0])
    		end
    	
    		return n_tri
    	end
    	
    	################################
    	# 出力
    	#      sw >=0 出力先未定
    	#           <0 ファイル
    	#      n_tri 現在の試行回数
    	#      r 距離
    	################################
    
    	def Output(sw, n_tri, r)
    	
    		k = 0
    	
    		if sw >= 0
    			print("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ")
    			pr = Integer($stdin.gets())
    		else
    			pr = -1
    		end
    	
    		if pr != 0
    	
    			if pr > 0
    				out = $stdout
    				$stdin.gets()
    			else
    				now = String(Time.now)
    				out = open(@_o_file, "a")
    				if @_seisu > -2
    					out.print("***試行回数 " + String(n_tri) + " 距離 " + String(int(r)) + " 時間 " + now + "\n")
    				else
    					out.print("***試行回数 " + String(n_tri) + " 距離 " + String(r) + " 時間 " + now + "\n")
    				end
    			end
    	
    			if @_out_m == 0
    				for i1 in 0 ... @_n_city
    					n = @_seq[i1]
    					if @_seisu > 0
    						out.write("  " + String(n) + " " + String(int(@_city[n][0])) + " " + String(int(@_city[n][1])) + "\n")
    					else
    						out.write("  " + String(n) + " " + String(@_city[n][0]) + " " + String(@_city[n][1]) + "\n")
    					end
    					if pr > 0
    						k += 1
    						if k == pr
    							$stdin.gets()
    							k = 0
    						end
    					end
    				end
    			end
    	
    			if pr <= 0
    				out.close()
    			end
    		end
    	end
    	
    	#######################################
    	# エッジの入れ替え
    	#      r_m 距離
    	#      return =0 改善がなかった
    	#               =1 改善があった
    	#######################################
    
    	def Change(r_m)
    	
    		max  = r_m[0]
    		max1 = 0.0
    		ch   = 0
    		k1   = 0
    		k2   = 0
    		n1   = 0
    		n2   = 0
    		sw   = 0
    		sw1  = 0
    				# 近傍を可変
    		if @_fix == 0
    						# 初期設定(k=2)
    			k = 2
    			for i1 in 0 ... @_n_city
    				@_seq_w4[i1] = @_seq[i1]
    				@_seq_w3[i1] = 0
    			end
    							# 評価
    			sw2 = 0
    			i0  = 0
    			while i0 < @_n_city-2 && sw2 < 2
    	
    				if i0 == 0
    					n = @_n_city - 1
    				else
    					n = @_n_city
    				end
    	
    				i1 = i0 + 2
    				while i1 < n && sw2 < 2
    								# 相手の場所
    					k3 = i1
    					k4 = k3 + 1
    					if k4 > @_n_city-1
    						k4 = 0
    					end
    								# 順番の入れ替え
    					n3 = -1
    					for i2 in 0 ... @_n_city
    						if @_seq_w4[i2] == @_seq[i0+1]
    							n3 = i2 + 1
    							break
    						end
    					end
    					nn = n3
    					n4 = -1
    					for i2 in 0 ... @_n_city
    						if nn > @_n_city-1
    							nn = 0
    						end
    						if @_seq_w4[nn] == @_seq[k3] || @_seq_w4[nn] == @_seq[k4]
    							n4 = @_seq_w4[nn]
    							break
    						else
    							nn += 1
    						end
    					end
    					if n4 == @_seq[k4]
    						n4 = k3
    						k3 = k4
    						k4 = n4
    					end
    								# 評価
    					@_seq_w1[0] = @_seq[k4]
    					@_seq_w1[1] = @_seq[i0+1]
    					n4          = -1
    					nn          = 2
    					while n4 < 0
    						if n3 > @_n_city-1
    							n3 = 0
    						end
    						@_seq_w1[nn] = @_seq_w4[n3]
    						if @_seq_w4[n3] == @_seq[k3]
    							n4 = 1
    						end
    						nn += 1
    						n3 += 1
    					end
    					@_seq_w1[nn] = @_seq[i0]
    					nn += 1
    					n3 = -1
    					n4 = -1
    					for i2 in 0 ... @_n_city
    						if @_seq_w4[i2] == @_seq[i0]
    							n3 = i2 - 1
    							if n3 < 0
    								n3 = @_n_city - 1
    							end
    							break
    						end
    					end
    					while n4 < 0
    						if @_seq_w4[n3] == @_seq[k4]
    							n4 = 1
    						else
    							@_seq_w1[nn] = @_seq_w4[n3]
    							nn += 1
    							n3 -= 1
    							if n3 < 0
    								n3 = @_n_city - 1
    							end
    						end
    					end
    	
    					r = kyori(@_n_city, @_seq_w1, @_rg)
    								# 最適値の保存
    					if sw2 == 0 || r < max1
    						sw2  = 1
    						max1 = r
    						n1   = k3
    						n2   = k4
    						k1   = i0
    						k2   = i0 + 1
    						for i2 in 0 ... @_n_city
    							@_seq_w5[i2] = @_seq_w1[i2]
    						end
    						if @_sel > 0 && max1 < max
    							sw2 = 2
    						end
    					end
    					i1 += 1
    				end
    				i0 += 1
    			end
    							# 最適値の保存と近傍の増加
    			if sw2 > 0
    				if max1 < max
    					sw  = 1
    					max = max1
    					for i1 in 0 ... @_n_city
    						@_seq_w2[i1] = @_seq_w5[i1]
    					end
    				end
    				if k < @_neib
    					for i1 in 0 ... @_n_city
    						@_seq_w4[i1] = @_seq_w5[i1]
    					end
    					@_seq_w3[k1] = 1
    					@_seq_w3[k2] = 1
    					@_seq_w3[n1] = 1
    					@_seq_w3[n2] = 1
    					k1           = n2
    					k += 1
    				else
    					sw1 = 1
    				end
    			else
    				sw1 = 1
    			end
    						# 実行(k>2)
    			while sw1 == 0
    							# 評価
    				sw2 = 0
    				for i1 in 0 ... @_n_city
    								# 相手の場所
    					k3 = i1
    					k4 = k3 + 1
    					if k4 > @_n_city-1
    						k4 = 0
    					end
    	
    					if @_seq_w3[k3] == 0 && @_seq_w3[k4] == 0
    								# 順番の入れ替え
    						n3 = -1
    						for i2 in 0 ... @_n_city
    							if @_seq_w4[i2] == @_seq[k2]
    								n3 = i2 + 1
    								break
    							end
    						end
    						nn = n3
    						n4 = -1
    						for i2 in 0 ... @_n_city
    							if nn > @_n_city-1
    								nn = 0
    							end
    							if @_seq_w4[nn] == @_seq[k3] || @_seq_w4[nn] == @_seq[k4]
    								n4 = @_seq_w4[nn]
    								break
    							else
    								nn += 1
    							end
    						end
    						if n4 == @_seq[k4]
    							n4 = k3
    							k3 = k4
    							k4 = n4
    						end
    								# 評価
    						@_seq_w1[0] = @_seq[k4]
    						@_seq_w1[1] = @_seq[k2]
    						n4             = -1
    						nn             = 2
    						while n4 < 0
    							if n3 > @_n_city-1
    								n3 = 0
    							end
    							@_seq_w1[nn] = @_seq_w4[n3]
    							if @_seq_w4[n3] == @_seq[k3]
    								n4 = 1
    							end
    							nn += 1
    							n3 += 1
    						end
    						@_seq_w1[nn] = @_seq[k1]
    						nn += 1
    						n3  = -1
    						n4  = -1
    						for i2 in 0 ... @_n_city
    							if @_seq_w4[i2] == @_seq[k1]
    								n3 = i2 - 1
    								if n3 < 0
    									n3 = @_n_city - 1
    								end
    								break
    							end
    						end
    						while n4 < 0
    							if @_seq_w4[n3] == @_seq[k4]
    								n4 = 1
    							else
    								@_seq_w1[nn] = @_seq_w4[n3]
    								nn += 1
    								n3 -= 1
    								if n3 < 0
    									n3 = @_n_city - 1
    								end
    							end
    						end
    	
    						r = kyori(@_n_city, @_seq_w1, @_rg)
    								# 最適値の保存
    						if sw2 == 0 || r < max1
    							sw2  = 1
    							max1 = r
    							n1   = k3
    							n2   = k4
    							for i2 in 0 ... @_n_city
    								@_seq_w5[i2] = @_seq_w1[i2]
    							end
    						end
    					end
    				end
    							# 最適値の保存と近傍の増加
    				if sw2 > 0
    					if max1 < max
    						sw  = 1
    						max = max1
    						for i1 in 0 ... @_n_city
    							@_seq_w2[i1] = @_seq_w5[i1]
    						end
    					end
    					if k < @_neib
    						for i1 in 0 ... @_n_city
    							@_seq_w4[i1] = @_seq_w5[i1]
    						end
    						@_seq_w3[n1] = 1
    						@_seq_w3[n2] = 1
    						k1             = n2
    						k += 1
    					else
    						sw1 = 1
    					end
    				else
    					sw1 = 1
    				end
    			end
    				# 近傍を固定
    		else
    			n3 = Integer(rand(0) * (@_n_city - 2))
    			if n3 > @_n_city-3
    				n3 = @_n_city - 3
    			end
    							 # 2近傍
    			i1 = 0
    			while i1 <= @_n_city-3 && ch == 0
    	
    				if n3 == 0
    					n1 = @_n_city - 2
    				else
    					n1 = @_n_city - 1
    				end
    	
    				i2 = n3 + 2
    				while i2 <= n1 && ch == 0
    								  # 枝の場所((n3,n3+1), (k1,k2))
    					k1 = i2
    					if i2 == @_n_city-1
    						k2 = 0
    					else
    						k2 = i2 + 1
    					end
    								  # 枝の入れ替え
    					@_seq_w1[0] = @_seq[n3]
    					k           = 1
    					i3          = k1
    					while i3 > n3
    						@_seq_w1[k] = @_seq[i3]
    						k  += 1
    						i3 -= 1
    					end
    	
    					nn = k2
    					while nn != n3
    						@_seq_w1[k] = @_seq[nn]
    						k  += 1
    						nn += 1
    						if nn > @_n_city-1
    							nn = 0
    						end
    					end
    								  # 評価
    					r = kyori(@_n_city, @_seq_w1, @_rg)
    	
    					if r < max
    						max = r
    						sw  = 1
    						for i3 in 0 ... @_n_city
    							@_seq_w2[i3] = @_seq_w1[i3]
    						end
    						if @_sel > 0
    							ch = 1
    						end
    					end
    					i2 += 1
    				end
    	
    				n3 += 1
    				if n3 > @_n_city-3
    					n3 = 0
    				end
    				i1 += 1
    			end
    							 # 3近傍
    			if @_neib == 3 && ch == 0
    	
    				i1 = 0
    				while i1 <= @_n_city-3 && ch == 0
    	
    					n1 = @_n_city - 2
    					n2 = @_n_city - 1
    	
    					i2 = n3 + 1
    					while i2 <= n1 && ch == 0
    	
    						i3 = i2 + 1
    						while i3 <= n2 && ch == 0
    								  # 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2))
    							k1 = i3
    							if i3 == @_n_city-1
    								k2 = 0
    							else
    								k2 = i3 + 1
    							end
    								  # 枝の入れ替えと評価
    									   # 入れ替え(その1)
    							@_seq_w1[0] = @_seq[n3]
    							k           = 1
    							i4          = i2
    							while i4 > n3
    								@_seq_w1[k] = @_seq[i4]
    								k  += 1
    								i4 -= 1
    							end
    	
    							i4 = k1
    							while i4 > i2
    								@_seq_w1[k] = @_seq[i4]
    								k  += 1
    								i4 -= 1
    							end
    	
    							nn = k2
    							while nn != n3
    								@_seq_w1[k] = @_seq[nn]
    								k  += 1
    								nn += 1
    								if nn > @_n_city-1
    									nn = 0
    								end
    							end
    									   # 評価(その1)
    							r = kyori(@_n_city, @_seq_w1, @_rg)
    	
    							if r < max
    								max = r
    								sw  = 1
    								for i3 in 0 ... @_n_city
    									@_seq_w2[i3] = @_seq_w1[i3]
    								end
    								if @_sel > 0
    									ch = 1
    								end
    							end
    									   # 入れ替え(その2)
    							@_seq_w1[0] = @_seq[n3]
    							k           = 1
    							i4          = k1
    							while i4 > i2
    								@_seq_w1[k] = @_seq[i4]
    								k  += 1
    								i4 -= 1
    							end
    	
    							for i4 in n3+1 ... i2+1
    								@_seq_w1[k] = @_seq[i4]
    								k += 1
    							end
    	
    							nn = k2
    							while nn != n3
    								@_seq_w1[k] = @_seq[nn]
    								k  += 1
    								nn += 1
    								if nn > @_n_city-1
    									nn = 0
    								end
    							end
    									   # 評価(その2)
    							r = kyori(@_n_city, @_seq_w1, @_rg)
    	
    							if r < max
    								max = r
    								sw  = 1
    								for i3 in 0 ...@_n_city
    									@_seq_w2[i3] = @_seq_w1[i3]
    								end
    								if @_sel > 0
    									ch = 1
    								end
    							end
    									   # 入れ替え(その3)
    							@_seq_w1[0] = @_seq[n3]
    							k           = 1
    							for i4 in i2+1 ...k1+1
    								@_seq_w1[k] = @_seq[i4]
    								k += 1
    							end
    	
    							i4 = i2
    							while i4 > n3
    								@_seq_w1[k] = @_seq[i4]
    								k  += 1
    								i4 -= 1
    							end
    	
    							nn = k2
    							while nn != n3
    								@_seq_w1[k] = @_seq[nn]
    								k  += 1
    								nn += 1
    								if nn > @_n_city-1
    									nn = 0
    								end
    							end
    									   # 評価(その3)
    							r = kyori(@_n_city, @_seq_w1, @_rg)
    	
    							if r < max
    								max = r
    								sw  = 1
    								for i3 in 0 ... @_n_city
    									@_seq_w2[i3] = @_seq_w1[i3]
    								end
    								if @_sel > 0
    									ch = 1
    								end
    							end
    									   # 入れ替え(その4)
    							@_seq_w1[0] = @_seq[n3]
    							k           = 1
    							for i4 in i2+1 ... k1+1
    								@_seq_w1[k] = @_seq[i4]
    								k += 1
    							end
    	
    							for i4 in n3+1 ... i2+1
    								@_seq_w1[k] = @_seq[i4]
    								k += 1
    							end
    	
    							nn = k2
    							while nn != n3
    								@_seq_w1[k] = @_seq[nn]
    								k  += 1
    								nn += 1
    								if nn > @_n_city-1
    									nn = 0
    								end
    							end
    									   # 評価(その4)
    							r = kyori(@_n_city, @_seq_w1, @_rg)
    	
    							if r < max
    								max = r
    								sw  = 1
    								for i3 in 0 ... @_n_city
    									@_seq_w2[i3] = @_seq_w1[i3]
    								end
    								if @_sel > 0
    									ch = 1
    								end
    							end
    							i3 += 1
    						end
    						i2 += 1
    					end
    	
    					n3 += 1
    					if n3 > @_n_city-3
    						n3 = 0
    					end
    					i1 += 1
    				end
    			end
    		end
    							 # 設定
    		if sw > 0
    			r_m[0] = max
    			for i1 in 0 ... @_n_city
    				@_seq[i1] = @_seq_w2[i1]
    			end
    		end
    	
    		return sw
    	end
    
    	attr("_seq", true)
    end
    	
    #########################
    # クラスPartitionの定義
    #########################
    
    class Partition
    
    	##########################
    	# コンストラクタ
    	#      name ファイル名
    	##########################
    
    	def initialize(name)
    	
    		max = 0
    						# ファイルのオープン
    		@_i_file = name   # 入力ファイル名
    		inn      = open(name, "r")
    						# 基本データ
    		s        = inn.gets().split(" ")
    		@_n_city = Integer(s[1])   # 都市の数
    		@_sel    = Integer(s[3])   # エッジの選択方法
    		                           #   =0 最良のものを選択
    		                           #   =1 最初のものを選択
    		@_neib   = Integer(s[5])   # 近傍(2 or 3)
    		@_seisu  = Integer(s[7])   # 位置データの表現方法
    		                           #   =1 整数
    		                           #   =-1 実数(距離を整数計算)
    		                           #   =-2 実数(距離を実数計算)
    		s        = inn.gets().split(" ")
    		@_out_m  = Integer(s[1])   # 出力方法
    		                           #   =-1 ディスプレイ(経路長だけ)
    		                           #   =0 ディスプレイ
    		                           #   =1 ファイル
    		                           #   =2 ファイル(経路長だけ)
    		@_o_file = ""
    		if @_out_m > 0
    			@_o_file = s[3]
    		end
    		s         = inn.gets().split(" ")
    		@_n_p_x   = Integer(s[2])   # x軸方向の分割数
    		@_n_p_y   = Integer(s[4])   # y軸方向の分割数
    		@_max_try = Integer(s[6])   # 最大試行回数
    	
    		@_fix = 1   # =1 近傍を固定
    		            # =0 近傍を可変
    		if @_neib < 0
    			@_neib = -@_neib
    			@_fix  = 0
    		end
    						# 都市の位置データ
    		@_city = Array.new(@_n_city)
    		for i1 in 0 ... @_n_city
    			@_city[i1]    = Array.new(2)
    			s             = inn.gets().split(" ")
    			@_city[i1][0] = Float(s[0])
    			@_city[i1][1] = Float(s[1])
    		end
    						# ファイルのクローズ
    		inn.close()
    						# 距離テーブルの作成
    		@_rg = Array.new(@_n_city)   # 都市間の距離
    
    		for i1 in 0 ... @_n_city
    			@_rg[i1] = Array.new(@_n_city)
    			for i2 in i1+1 ... @_n_city
    				x = @_city[i2][0] - @_city[i1][0]
    				y = @_city[i2][1] - @_city[i1][1]
    				@_rg[i1][i2] = Math.sqrt(x * x + y * y)
    				if @_seisu > -2
    					@_rg[i1][i2] = rg[i1][i2].round()
    				end
    			end
    		end
    	
    		for i1 in 0 ... @_n_city
    			for i2 in 0 ... i1
    				@_rg[i1][i2] = @_rg[i2][i1]
    			end
    		end
    						# 作業領域
    		@_state  = Array.new(@_n_p_y)   # 領域結合用ワーク
    		@_n_seq  = Array.new(@_n_p_y)   # 各領域の都市数
    		@_n_seq1 = Array.new(@_n_p_y)   # 各領域の都市数(ワーク)
    		for i1 in 0 ... @_n_p_y
    			@_state[i1]  = Array.new(@_n_p_x)   # 領域結合用ワーク
    			@_n_seq[i1]  = Array.new(@_n_p_x)   # 各領域の都市数
    			@_n_seq1[i1] = Array.new(@_n_p_x)   # 各領域の都市数(ワーク)
    		end
    		@_seq_w1 = Array.new(@_n_city)   # 作業領域
    		for i1 in 0 ... @_n_city
    			@_seq_w1[i1] = 0
    		end
    		@_seq_w2 = Array.new(@_n_city)   # 作業領域
    		@_p_x    = Array.new(@_n_p_x)   # x軸の分割点
    		@_p_y    = Array.new(@_n_p_y)   # y軸の分割点
    						# 都市の分割
    		min_x = @_city[0][0]
    		max_x = @_city[0][0]
    		min_y = @_city[0][1]
    		max_y = @_city[0][1]
    	
    		for i1 in 1 ... @_n_city
    			if @_city[i1][0] < min_x
    				min_x = @_city[i1][0]
    			else
    				if @_city[i1][0] > max_x
    					max_x = @_city[i1][0]
    				end
    			end
    			if @_city[i1][1] < min_y
    				min_y = @_city[i1][1]
    			else
    				if @_city[i1][1] > max_y
    					max_y = @_city[i1][1]
    				end
    			end
    		end
    	
    		s_x                    = (max_x - min_x) / @_n_p_x
    		@_p_x[0]            = min_x + s_x
    		@_p_x[@_n_p_x-1] = max_x
    		for i1 in 1 ... @_n_p_x-1
    			@_p_x[i1] = @_p_x[0] + i1 * s_x
    		end
    	
    		s_y              = (max_y - min_y) / @_n_p_y
    		@_p_y[0]         = min_y + s_y
    		@_p_y[@_n_p_y-1] = max_y
    		for i1 in 1 ... @_n_p_y-1
    			@_p_y[i1] = @_p_y[0] + i1 * s_y
    		end
    	
    		@_seq  = Array.new(@_n_p_y)   # 経路
    		@_seq1 = Array.new(@_n_p_y)   # 経路(ワーク)
    		for i1 in 0 ... @_n_p_y
    			@_seq[i1]  = Array.new(@_n_p_x)
    			@_seq1[i1] = Array.new(@_n_p_x)
    			for i2 in 0 ... @_n_p_x
    				@_seq[i1][i2]  = Array.new(@_n_city)
    				@_seq1[i1][i2] = Array.new(@_n_city)
    				n              = 0
    				for i3 in 0 ... @_n_city
    					if @_seq_w1[i3] == 0
    						if @_city[i3][0] <= @_p_x[i2] && @_city[i3][1] <= @_p_y[i1]
    							@_seq_w1[i3] = 1
    							@_seq_w2[n]  = i3
    							n += 1
    						end
    					end
    				end
    				@_n_seq1[i1][i2] = n
    				if n > 0
    					for i3 in 0 ... n
    						@_seq1[i1][i2][i3] = @_seq_w2[i3]
    					end
    					if n > max
    						max = n
    					end
    				end
    			end
    		end
    						# 作業領域
    		print("最大都市数 " + String(max) + "\n")
    		@_city_i = Array.new(max)   # 都市の位置データ(作業領域)
    		for i1 in 0 ... max
    			@_city_i[i1]    = Array.new(2)
    		end
    		@_max = 0   # 最適経路の長さ
    	end
    
    	##################
    	# 最適化の実行
    	##################
    
    	def Optimize()
    	
    		r = 0
    						# 分割数と開始時間の出力
    		if @_out_m > 0
    			Output(0, r)
    		end
    	
    		for i1 in 0 ... @_n_p_y
    			for i2 in 0 ... @_n_p_x
    				@_n_seq[i1][i2] = @_n_seq1[i1][i2]
    				for i3 in 0 ... @_n_seq1[i1][i2]
    					@_seq[i1][i2][i3] = @_seq1[i1][i2][i3]
    				end
    			end
    		end
    						# 分割毎の最適化
    		for i1 in 0 ... @_n_p_y
    			for i2 in 0 ... @_n_p_x
    				if @_n_seq[i1][i2] > 3
    							# 近傍の大きさ
    					if @_n_seq[i1][i2] > 3
    						nb = @_neib
    					else
    						nb = 2
    					end
    							# 都市位置データの設定
    					for i3 in 0 ... @_n_seq[i1][i2]
    						k               = @_seq[i1][i2][i3]
    						@_city_i[i3][0] = @_city[k][0]
    						@_city_i[i3][1] = @_city[k][1]
    					end
    							# 最適化
    					it  = Iteration.new(@_n_seq[i1][i2], @_max_try, @_seisu, @_sel, nb, @_fix, 0, -1, 0, @_o_file, @_city_i)
    					max = it.Optimize()
    							# 結果の保存
    					for i3 in 0 ... @_n_seq[i1][i2]
    						k            = it._seq[i3]
    						@_seq_w1[i3] = @_seq[i1][i2][k]
    					end
    					for i3 in 0 ... @_n_seq[i1][i2]
    						@_seq[i1][i2][i3] = @_seq_w1[i3]
    					end
    							# 出力
    					if @_seisu > -2
    						r = Integer(kyori(@_n_seq[i1][i2], @_seq[i1][i2], @_rg))
    					else
    						r = kyori(@_n_seq[i1][i2], @_seq[i1][i2], @_rg).round()
    					print("   y " + String(i1+1) + " x " + String(i2+1) + " n_city " + String(@_n_seq[i1][i2]) + " range " + String(r) + " (trial " + String(max) + ")\n")
    					end
    				end
    			end
    		end
    						# 経路の接続
    		r = Connect()
    						# 出力
    		Output(@_n_city, r)
    	end
    	
    	########################
    	# 出力
    	#      n_c 都市の数
    	#      r 距離
    	########################
    
    	def Output(n_c, r)
    	
    		k = 0
    	
    		if @_out_m <= 0
    			print("距離 " + String(r) + "\n")
    			out = $stdout
    			$stdin.gets()
    		else
    			now = String(Time.now)
    			out = open(@_o_file, "a")
    			if n_c > 0
    				print("距離 " + String(r) + "\n")
    				printf(out, "   距離 " + String(r) + " 時間 " + now + "\n")
    			else
    				printf("問題 " + @_i_file + " 分割 " + String(@_n_p_x) + " " + String(@_n_p_y) + " 時間 " + now + "\n")
    			end
    		end
    	
    		if n_c > 0 && (@_out_m == 0 || @_out_m == 1)
    			for i1 in 0 ... n_c
    				n = @_seq_w1[i1]
    				if @_seisu > 0
    					out.print("  " + String(n) + " " + String(int(@_city[n][0])) + " " + String(int(@_city[n][1])) + "\n")
    				else
    					out.print("  " + String(n) + " " + String(@_city[n][0]) + " " + String(@_city[n][1]) + "\n")
    				end
    				if @_out_m == 0
    					k += 1
    					if k == 10
    						$stdin.gets()
    						k = 0
    					end
    				end
    			end
    		end
    	
    		if @_out_m > 0
    			out.close()
    		end
    	end
    	
    	########################
    	# 分割された領域の接続
    	########################
    
    	def Connect()
    	
    		min   = 0
    		k1    = 0
    		k2    = 0
    		k3    = 0
    		k4    = 0
    		min_c = 0
    		r1    = 0
    		r2    = 0
    		r3    = 0
    		r4    = 0
    		s1    = 0
    		s2    = 0
    		sw    = 1
    				# 領域が1つの場合
    		if @_n_p_x == 1 && @_n_p_y == 1
    			for i1 in 0 ... @_n_seq[0][0]
    				@_seq_w1[i1] = @_seq[0][0][i1]
    			end
    				# 初期設定
    		else
    	
    			for i1 in 0 ... @_n_p_y
    				for i2 in 0 ... @_n_p_x
    					if @_n_seq[i1][i2] > 0
    						@_state[i1][i2] = 0
    					else
    						@_state[i1][i2] = 1
    					end
    				end
    			end
    				# 実行
    			while sw > 0
    						# 最小節点領域
    				min_c = @_n_city
    				sw    = 0
    				for i1 in 0 ... @_n_p_y
    					for i2 in 0 ... @_n_p_x
    						if @_state[i1][i2] == 0 && @_n_seq[i1][i2] < min_c
    							sw    = 1
    							r1    = i1
    							r2    = i2
    							min_c = @_n_seq[i1][i2]
    						end
    					end
    				end
    						# 結合する対象領域の決定
    				if sw > 0
    					sw = 0
    					for i1 in 0 ... @_n_p_y
    						for i2 in 0 ... @_n_p_x
    							if @_state[i1][i2] == 0 && (i1 != r1 || i2 != r2)
    									# 節点の数>2
    								if @_n_seq[r1][r2] > 1
    									for i3 in 0 ... @_n_seq[r1][r2]
    										k1 = @_seq[r1][r2][i3]
    										if i3 == @_n_seq[r1][r2]-1
    											k2 = @_seq[r1][r2][0]
    										else
    											k2 = @_seq[r1][r2][i3+1]
    										end
    										wd1 = @_rg[k1][k2]
    										for i4 in 0 ... @_n_seq[i1][i2]
    											k3  = @_seq[i1][i2][i4]
    											if i4 == @_n_seq[i1][i2]-1
    												k4 = @_seq[i1][i2][0]
    											else
    												k4 = @_seq[i1][i2][i4+1]
    											end
    											wd  = wd1 + @_rg[k3][k4]
    											wa1 = @_rg[k1][k3] + @_rg[k2][k4]
    											wa2 = @_rg[k1][k4] + @_rg[k2][k3]
    											if sw == 0 || wa1-wd < min
    												min = wa1 - wd
    												r3  = i1
    												r4  = i2
    												if i3 == @_n_seq[r1][r2]-1
    													s1 = 0
    												else
    													s1 = i3 + 1
    												end
    												if i4 == @_n_seq[i1][i2]-1
    													s2 = 0
    												else
    													s2 = i4 + 1
    												end
    												sw = -1
    											end
    											if sw == 0 || wa2-wd < min
    												min = wa2 - wd
    												r3  = i1
    												r4  = i2
    												s1  = i3
    												if i4 == @_n_seq[i1][i2]-1
    													s2 = 0
    												else
    													s2 = i4 + 1
    												end
    												sw = 1
    											end
    										end
    									end
    									# 節点の数=1
    								else
    									k1 = @_seq[r1][r2][0]
    									if @_n_seq[i1][i2] > 1
    										for i4 in 0 ... @_n_seq[i1][i2]
    											k3  = @_seq[i1][i2][i4]
    											if i4 == @_n_seq[i1][i2]-1
    												k4 = @_seq[i1][i2][0]
    											else
    												k4 = @_seq[i1][i2][i4+1]
    											end
    											wd  = @_rg[k3][k4]
    											wa1 = @_rg[k1][k3] + @_rg[k1][k4]
    											if sw == 0 || wa1-wd < min
    												min = wa1 - wd
    												r3  = i1
    												r4  = i2
    												s1  = 0
    												if i4 == @_n_seq[i1][i2]-1
    													s2 = 0
    												else
    													s2 = i4 + 1
    												end
    												sw = 1
    											end
    										end
    									else
    										k3  = @_seq[i1][i2][0]
    										wa1 = @_rg[k1][k3]
    										if sw == 0 || wa1 < min
    											min = wa1
    											r3  = i1
    											r4  = i2
    											s1  = 0
    											s2  = 0
    											sw  = 1
    										end
    									end
    								end
    							end
    						end
    					end
    						# 領域の結合
    					@_seq_w1[0] = @_seq[r1][r2][s1]
    					k           = 1
    					n           = s2
    					for i1 in 0 ... @_n_seq[r3][r4]
    						@_seq_w1[k] = @_seq[r3][r4][n]
    						k += 1
    						n += 1
    						if n > @_n_seq[r3][r4]-1
    							n = 0
    						end
    					end
    					if sw > 0
    						n = s1 + 1
    						for i1 in 0 ... @_n_seq[r1][r2]-1
    							if n > @_n_seq[r1][r2]-1
    								n = 0
    							end
    							@_seq_w1[k] = @_seq[r1][r2][n]
    							k += 1
    							n += 1
    						end
    					else
    						n = s1 - 1
    						for i1 in 0 ... @_n_seq[r1][r2]-1
    							if n < 0
    								n = @_n_seq[r1][r2] - 1
    							end
    							@_seq_w1[k] = @_seq[r1][r2][n]
    							k += 1
    							n -= 1
    						end
    					end
    						# 状態の変更
    					@_n_seq[r1][r2] += @_n_seq[r3][r4]
    					@_state[r3][r4]  = 1
    					for i1 in 0 ... @_n_seq[r1][r2]
    						@_seq[r1][r2][i1] = @_seq_w1[i1]
    					end
    					sw = 1
    				end
    			end
    		end
    	
    		if @_seisu > -2
    			r = Integer(kyori(@_n_city, @_seq_w1, @_rg))
    		else
    			r = kyori(@_n_city, @_seq_w1, @_rg).round()
    		end
    		@_max = r
    	
    		return r
    	end
    
    	attr("_out_m", true)
    	attr("_o_file", true)
    	attr("_max", true)
    end
    			# 入力ミス
    if ARGV[0] == nil
    	print("***error  ファイル名を入力して下さい\n")
    			# 入力OK
    else
    				# 問題数と入力データファイル名
    	line = gets()
    	a    = line.split(" ")
    	nm   = Integer(a[1])
    	aa   = Array.new(nm)
    	for i0 in 0 ... nm
    		aa[i0] = gets()
    	end
    	for i0 in 0 ... nm
    					# 各問題の実行
    		a      = aa[i0].split(" ")
    		i_file = a[1]
    		n      = Integer(a[3])
    		pt     = Partition.new(i_file)
    		mean   = 0.0
    		max    = -1
    						# 乱数の初期値を変える
    		for i1 in 0 ... n
    			print("\n+++++問題 " + i_file + " +++++\n")
    			srand(1000 * i1 + 1234567);
    							# 最適化
    			pt.Optimize()
    							# 最適値とその平均の計算
    			mean += pt._max
    			if max < 0 or pt._max < max
    				max = pt._max
    			end
    		end
    					# 結果
    		if pt._out_m <= 0
    			print("     -----最小 " + String(max) + " 平均 " + String(mean/n) + "-----\n")
    		else
    			out = open(pt._o_file, "a")
    			out = open("out.txt", "a")
    			printf(out, "     -----最小 " + String(max) + " 平均 " + String(mean/n) + "-----\n")
    			out.close()
    		end
    	end
    end
    
    =begin
    ------------------------ケーススタディデータ(data.txt)------
    問題の数 2
    問題 data1.txt 繰り返し回数 2
    問題 data2.txt 繰り返し回数 1
    
    ---------------------データファイル(data1.txt)------------
    都市の数 50 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 2 Y 2 最大試行回数 1000
    86.950684 27.711487
    82.357788 16.148376
    29.791260 37.959290
    27.493286 1.542664
    90.893555 88.734436
    40.109253 92.308044
    87.445068 53.474426
    24.893188 99.382019
    11.633301 80.616760
    61.532593 8.702087
    30.645752 93.598938
    4.714966 81.205750
    86.669922 90.858459
    84.127808 52.830505
    96.893311 45.832825
    4.458618 34.513855
    53.503418 6.959534
    45.394897 12.193298
    23.687744 97.676086
    61.624146 46.806335
    49.633789 16.419983
    82.833862 74.290466
    48.529053 36.628723
    13.711548 5.583191
    12.561035 6.739807
    33.944702 26.622009
    8.917236 50.190735
    98.220825 98.344421
    79.785156 65.419006
    36.227417 56.687927
    42.352295 25.862122
    52.651978 12.590027
    88.806152 79.957581
    27.182007 51.988220
    86.334229 51.142883
    14.505005 35.820007
    77.124023 37.855530
    44.308472 0.022888
    78.363037 13.533020
    21.279907 55.534363
    82.238770 26.612854
    25.106812 88.291931
    55.938721 0.532532
    10.476685 59.233093
    41.650391 33.729553
    7.077026 4.295349
    56.561279 99.641418
    19.595337 34.416199
    92.858887 46.705627
    27.719116 35.533142
    
    ---------------------データファイル(data2.txt)------------
    都市の数 10 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 1 Y 1 最大試行回数 1000
    8.695068 2.771149
    8.235779 1.614838
    2.979126 3.795929
    2.749329 0.154266
    9.089355 8.873444
    4.010925 9.230804
    8.744507 5.347443
    2.489319 9.938202
    1.163330 8.061676
    6.153259 0.870209
    =end
    			

  5. Python

    # -*- coding: UTF-8 -*-
    import numpy as np
    import sys
    from math import *
    from random import *
    from datetime import *
    
    #################################
    # 距離の計算
    #      n_c : 都市の数
    #      p : 都市番号
    #      rg : 都市間の距離
    #      return : 距離
    #################################
    
    def kyori(n_c, p, rg) :
    
    	r  = 0.0
    	n1 = p[0]
    
    	for i1 in range(1, n_c) :
    		n2  = p[i1]
    		r  += rg[n1][n2]
    		n1  = n2
    
    	n2  = p[0]
    	r  += rg[n1][n2]
    
    	return r
    
    #########################
    # クラスIterationの定義
    #########################
    
    class Iteration :
    	
    	###################################
    	# コンストラクタ
    	#      n_city_i : 都市の数
    	#      max_try_i : 最大試行回数
    	#      sei_i : 整数 or 実数
    	#      sel_i : エッジの選択方法
    	#      neib_i : 近傍
    	#      fix_i : 近傍の扱い方
    	#      out_lvl_i : 出力レベル
    	#      out_m_i : 出力方法
    	#      out_d_i : 表示間隔
    	#      o_file_i : 出力ファイル名
    	#      city_i : 都市の位置データ
    	###################################
    
    	def __init__(self, n_city_i, max_tri_i, sei_i, sel_i, neib_i, fix_i, out_lvl_i, out_m_i, out_d_i, o_file_i, city_i) :
    						# 値の設定
    		self.n_city  = n_city_i   # 都市の数
    		self.max_try = max_tri_i   # 最大試行回数
    		self.seisu   = sei_i   # 位置データの表現方法
    		                       #   =1 : 整数
    		                       #   =-1 : 実数(距離を整数計算)
    		                       #   =-2 : 実数(距離を実数計算)
    		self.sel     = sel_i   # エッジの選択方法
    		                       #   =0 : 最良のものを選択
    		                       #   =1 : 最初のものを選択
    		self.neib    = neib_i   # 近傍(2 or 3)
    		self.fix     = fix_i   # =1 : 近傍を固定
    		                       # =0 : 近傍を可変
    		self.out_lvl = out_lvl_i   # 出力レベル
    		                           #   =0 : 最終出力だけ
    		                           #   n>0 : n世代毎に出力(負の時はファイル)
    		self.out_m   = out_m_i   # 出力方法
    		                         #   =-1 : 出力しない
    		                         #   =0 : すべてを出力
    		                         #   =1 : 評価値だけを出力(最終結果だけはすべてを出力)
    		self.out_d   = out_d_i   # 表示間隔
    		self.o_file  = o_file_i   # 出力ファイル名
    		self.city    = city_i   # 都市の位置データ
    						# 距離テーブルの作成
    		self.rg = np.empty((self.n_city, self.n_city), np.float)
    	
    		for i1 in range(0, self.n_city-1) :
    			for i2 in range(i1+1, self.n_city) :
    				x = self.city[i2][0] - self.city[i1][0]
    				y = self.city[i2][1] - self.city[i1][1]
    				self.rg[i1][i2] = sqrt(x * x + y * y)
    				if self.seisu > -2 :
    					self.rg[i1][i2] = floor(self.rg[i1][i2] + 0.5)
    	
    		for i1 in range(1, self.n_city) :
    			for i2 in range(0, i1) :
    				self.rg[i1][i2] = self.rg[i2][i1]
    						# 都市を訪れる順序(初期設定)
    		self.seq    = np.empty(self.n_city, np.int)
    		self.seq_w1 = np.empty(self.n_city, np.int)
    		self.seq_w2 = np.empty(self.n_city, np.int)
    		self.seq_w3 = np.empty(self.n_city, np.int)
    		self.seq_w4 = np.empty(self.n_city, np.int)
    		self.seq_w5 = np.empty(self.n_city, np.int)
    	
    		for i1 in range(0, self.n_city) :
    			sw = 0
    			while sw == 0 :
    				ct = int(random() * self.n_city)
    				if ct >= self.n_city :
    					ct = self.n_city - 1
    				self.seq[i1] = ct
    				sw           = 1
    				for i2 in range(0, i1) :
    					if ct == self.seq[i2] :
    						sw = 0
    						break
    
    	################
    	# 最適化の実行
    	################
    
    	def Optimize (self) :
    						# 初期設定
    		n_tri  = 0
    		max    = np.empty(1, np.float)
    		max[0] = kyori(self.n_city, self.seq, self.rg)
    	
    		if self.out_m >= 0 and abs(self.out_lvl) > 0 :
    			if self.seisu > -2 :
    				print("***試行回数 " + str(n_tri) + " 距離 " + str(int(max[0])))
    			else :
    				print("***試行回数 " + str(n_tri) + " 距離 " + str(max[0]))
    			self.Output(self.out_lvl, n_tri, max[0])
    						# 実行
    		sw = 1
    		for n_tri in range(1, self.max_try+1) :
    							# 改善
    			sw = self.Change(max)
    							# 出力
    			if self.out_d > 0 and n_tri%self.out_d == 0 :
    				if self.seisu > -2 :
    					print("***試行回数 " + str(n_tri) + " 距離 " + str(int(max[0])))
    				else :
    					print("***試行回数 " + str(n_tri) + " 距離 " + str(max[0]))
    	
    			if self.out_m >= 0 and abs(self.out_lvl) > 0 :
    				if n_tri%abs(self.out_lvl) == 0 :
    					self.Output(self.out_lvl, n_tri, max[0])
    			if sw <= 0 :
    				break
    						# 最終出力
    		if self.out_m >= 0 :
    			n_tri -= 1
    			if self.seisu > -2 :
    				print("***試行回数 " + str(n_tri) + " 距離 " + str(int(max[0])))
    			else :
    				print("***試行回数 " + str(n_tri) + " 距離 " + str(max[0]))
    			self.Output(self.out_lvl, n_tri, max[0])
    	
    		return n_tri
    	
    	################################
    	# 出力
    	#      sw : >=0 : 出力先未定
    	#           <0 : ファイル
    	#      n_tri : 現在の試行回数
    	#      r : 距離
    	################################
    
    	def Output(self, sw, n_tri, r) :
    	
    		k = 0
    	
    		if sw >= 0 :
    			pr = int(input("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? "))
    		else :
    			pr = -1
    	
    		if pr != 0 :
    	
    			if pr > 0 :
    				out = sys.stdout
    				input("")
    			else :
    				now = datetime.today().time().isoformat()
    				out = open(self.o_file, "a")
    				if self.seisu > -2 :
    					out.write("***試行回数 " + str(n_tri) + " 距離 " + str(int(r)) + " 時間 " + now + "\n")
    				else :
    					out.write("***試行回数 " + str(n_tri) + " 距離 " + str(r) + " 時間 " + now + "\n")
    	
    			if self.out_m == 0 :
    				for i1 in range(0, self.n_city) :
    					n = self.seq[i1]
    					if self.seisu > 0 :
    						out.write("  " + str(n) + " " + str(int(self.city[n][0])) + " " + str(int(self.city[n][1])) + "\n")
    					else :
    						out.write("  " + str(n) + " " + str(self.city[n][0]) + " " + str(self.city[n][1]) + "\n")
    					if pr > 0 :
    						k += 1
    						if k == pr :
    							input("")
    							k = 0
    	
    			if pr <= 0 :
    				out.close()
    	
    	#######################################
    	# エッジの入れ替え
    	#      r_m : 距離
    	#      return : =0 : 改善がなかった
    	#               =1 : 改善があった
    	#######################################
    
    	def Change(self, r_m) :
    	
    		max  = r_m[0]
    		max1 = 0.0
    		ch   = 0
    		k1   = 0
    		k2   = 0
    		n1   = 0
    		n2   = 0
    		sw   = 0
    		sw1  = 0
    				# 近傍を可変
    		if self.fix == 0 :
    						# 初期設定(k=2)
    			k = 2
    			for i1 in range(0, self.n_city) :
    				self.seq_w4[i1] = self.seq[i1]
    				self.seq_w3[i1] = 0
    							# 評価
    			sw2 = 0
    			i0  = 0
    			while i0 < self.n_city-2 and sw2 < 2 :
    	
    				if i0 == 0 :
    					n = self.n_city - 1
    				else :
    					n = self.n_city
    	
    				i1 = i0 + 2
    				while i1 < n and sw2 < 2 :
    								# 相手の場所
    					k3 = i1
    					k4 = k3 + 1
    					if k4 > self.n_city-1 :
    						k4 = 0
    								# 順番の入れ替え
    					n3 = -1
    					for i2 in range(0, self.n_city) :
    						if self.seq_w4[i2] == self.seq[i0+1] :
    							n3 = i2 + 1
    							break
    					nn = n3
    					n4 = -1
    					for i2 in range(0, self.n_city) :
    						if nn > self.n_city-1 :
    							nn = 0
    						if self.seq_w4[nn] == self.seq[k3] or self.seq_w4[nn] == self.seq[k4] :
    							n4 = self.seq_w4[nn]
    							break
    						else :
    							nn += 1
    					if n4 == self.seq[k4] :
    						n4 = k3
    						k3 = k4
    						k4 = n4
    								# 評価
    					self.seq_w1[0] = self.seq[k4]
    					self.seq_w1[1] = self.seq[i0+1]
    					n4             = -1
    					nn             = 2
    					while n4 < 0 :
    						if n3 > self.n_city-1 :
    							n3 = 0
    						self.seq_w1[nn] = self.seq_w4[n3]
    						if self.seq_w4[n3] == self.seq[k3] :
    							n4 = 1
    						nn += 1
    						n3 += 1
    					self.seq_w1[nn] = self.seq[i0]
    					nn += 1
    					n3 = -1
    					n4 = -1
    					for i2 in range(0, self.n_city) :
    						if self.seq_w4[i2] == self.seq[i0] :
    							n3 = i2 - 1
    							if n3 < 0 :
    								n3 = self.n_city - 1
    							break
    					while n4 < 0 :
    						if self.seq_w4[n3] == self.seq[k4] :
    							n4 = 1
    						else :
    							self.seq_w1[nn] = self.seq_w4[n3]
    							nn += 1
    							n3 -= 1
    							if n3 < 0 :
    								n3 = self.n_city - 1
    	
    					r = kyori(self.n_city, self.seq_w1, self.rg)
    								# 最適値の保存
    					if sw2 == 0 or r < max1 :
    						sw2  = 1
    						max1 = r
    						n1   = k3
    						n2   = k4
    						k1   = i0
    						k2   = i0 + 1
    						for i2 in range(0, self.n_city) :
    							self.seq_w5[i2] = self.seq_w1[i2]
    						if self.sel > 0 and max1 < max :
    							sw2 = 2
    					i1 += 1
    				i0 += 1
    							# 最適値の保存と近傍の増加
    			if sw2 > 0 :
    				if max1 < max :
    					sw  = 1
    					max = max1
    					for i1 in range(0, self.n_city) :
    						self.seq_w2[i1] = self.seq_w5[i1]
    				if k < self.neib :
    					for i1 in range(0, self.n_city) :
    						self.seq_w4[i1] = self.seq_w5[i1]
    					self.seq_w3[k1] = 1
    					self.seq_w3[k2] = 1
    					self.seq_w3[n1] = 1
    					self.seq_w3[n2] = 1
    					k1              = n2
    					k += 1
    				else :
    					sw1 = 1
    			else :
    				sw1 = 1
    						# 実行(k>2)
    			while sw1 == 0 :
    							# 評価
    				sw2 = 0
    				for i1 in range(0, self.n_city) :
    								# 相手の場所
    					k3 = i1
    					k4 = k3 + 1
    					if k4 > self.n_city-1 :
    						k4 = 0
    	
    					if self.seq_w3[k3] == 0 and self.seq_w3[k4] == 0 :
    								# 順番の入れ替え
    						n3 = -1
    						for i2 in range(0, self.n_city) :
    							if self.seq_w4[i2] == self.seq[k2] :
    								n3 = i2 + 1
    								break
    						nn = n3
    						n4 = -1
    						for i2 in range(0, self.n_city) :
    							if nn > self.n_city-1 :
    								nn = 0
    							if self.seq_w4[nn] == self.seq[k3] or self.seq_w4[nn] == self.seq[k4] :
    								n4 = self.seq_w4[nn]
    								break
    							else :
    								nn += 1
    						if n4 == self.seq[k4] :
    							n4 = k3
    							k3 = k4
    							k4 = n4
    								# 評価
    						self.seq_w1[0] = self.seq[k4]
    						self.seq_w1[1] = self.seq[k2]
    						n4             = -1
    						nn             = 2
    						while n4 < 0 :
    							if n3 > self.n_city-1 :
    								n3 = 0
    							self.seq_w1[nn] = self.seq_w4[n3]
    							if self.seq_w4[n3] == self.seq[k3] :
    								n4 = 1
    							nn += 1
    							n3 += 1
    						self.seq_w1[nn] = self.seq[k1]
    						nn += 1
    						n3  = -1
    						n4  = -1
    						for i2 in range(0, self.n_city) :
    							if self.seq_w4[i2] == self.seq[k1] :
    								n3 = i2 - 1
    								if n3 < 0 :
    									n3 = self.n_city - 1
    								break
    						while n4 < 0 :
    							if self.seq_w4[n3] == self.seq[k4] :
    								n4 = 1
    							else :
    								self.seq_w1[nn] = self.seq_w4[n3]
    								nn += 1
    								n3 -= 1
    								if n3 < 0 :
    									n3 = self.n_city - 1
    	
    						r = kyori(self.n_city, self.seq_w1, self.rg)
    								# 最適値の保存
    						if sw2 == 0 or r < max1 :
    							sw2  = 1
    							max1 = r
    							n1   = k3
    							n2   = k4
    							for i2 in range(0, self.n_city) :
    								self.seq_w5[i2] = self.seq_w1[i2]
    							# 最適値の保存と近傍の増加
    				if sw2 > 0 :
    					if max1 < max :
    						sw  = 1
    						max = max1
    						for i1 in range(0, self.n_city) :
    							self.seq_w2[i1] = self.seq_w5[i1]
    					if k < self.neib :
    						for i1 in range(0, self.n_city) :
    							self.seq_w4[i1] = self.seq_w5[i1]
    						self.seq_w3[n1] = 1
    						self.seq_w3[n2] = 1
    						k1             = n2
    						k += 1
    					else :
    						sw1 = 1
    				else :
    					sw1 = 1
    				# 近傍を固定
    		else :
    			n3 = int(random() * (self.n_city - 2))
    			if n3 > self.n_city-3 :
    				n3 = self.n_city - 3
    							 # 2近傍
    			i1 = 0
    			while i1 <= self.n_city-3 and ch == 0 :
    	
    				if n3 == 0 :
    					n1 = self.n_city - 2
    				else :
    					n1 = self.n_city - 1
    	
    				i2 = n3 + 2
    				while i2 <= n1 and ch == 0 :
    								  # 枝の場所((n3,n3+1), (k1,k2))
    					k1 = i2
    					if i2 == self.n_city-1 :
    						k2 = 0
    					else :
    						k2 = i2 + 1
    								  # 枝の入れ替え
    					self.seq_w1[0] = self.seq[n3]
    					k              = 1
    					for i3 in range(k1, n3, -1) :
    						self.seq_w1[k] = self.seq[i3]
    						k += 1
    	
    					nn = k2
    					while nn != n3 :
    						self.seq_w1[k] = self.seq[nn]
    						k  += 1
    						nn += 1
    						if nn > self.n_city-1 :
    							nn = 0
    								  # 評価
    					r = kyori(self.n_city, self.seq_w1, self.rg)
    	
    					if r < max :
    						max = r
    						sw  = 1
    						for i3 in range(0, self.n_city) :
    							self.seq_w2[i3] = self.seq_w1[i3]
    						if self.sel > 0 :
    							ch = 1
    					i2 += 1
    	
    				n3 += 1
    				if n3 > self.n_city-3 :
    					n3 = 0
    				i1 += 1
    							 # 3近傍
    			if self.neib == 3 and ch == 0 :
    	
    				i1 = 0
    				while i1 <= self.n_city-3 and ch == 0 :
    	
    					n1 = self.n_city - 2
    					n2 = self.n_city - 1
    	
    					i2 = n3 + 1
    					while i2 <= n1 and ch == 0 :
    	
    						i3 = i2 + 1
    						while i3 <= n2 and ch == 0 :
    								  # 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2))
    							k1 = i3
    							if i3 == self.n_city-1 :
    								k2 = 0
    							else :
    								k2 = i3 + 1
    								  # 枝の入れ替えと評価
    									   # 入れ替え(その1)
    							self.seq_w1[0] = self.seq[n3]
    							k              = 1
    							for i4 in range(i2, n3, -1) :
    								self.seq_w1[k] = self.seq[i4]
    								k += 1
    	
    							for i4 in range(k1, i2, -1) :
    								self.seq_w1[k] = self.seq[i4]
    								k += 1
    	
    							nn = k2
    							while nn != n3 :
    								self.seq_w1[k] = self.seq[nn]
    								k  += 1
    								nn += 1
    								if nn > self.n_city-1 :
    									nn = 0
    									   # 評価(その1)
    							r = kyori(self.n_city, self.seq_w1, self.rg)
    	
    							if r < max :
    								max = r
    								sw  = 1
    								for i3 in range(0, self.n_city) :
    									self.seq_w2[i3] = self.seq_w1[i3]
    								if self.sel > 0 :
    									ch = 1
    									   # 入れ替え(その2)
    							self.seq_w1[0] = self.seq[n3]
    							k              = 1
    							for i4 in range(k1, i2, -1) :
    								self.seq_w1[k] = self.seq[i4]
    								k += 1
    	
    							for i4 in range(n3+1, i2+1) :
    								self.seq_w1[k] = self.seq[i4]
    								k += 1
    	
    							nn = k2
    							while nn != n3 :
    								self.seq_w1[k] = self.seq[nn]
    								k  += 1
    								nn += 1
    								if nn > self.n_city-1 :
    									nn = 0
    									   # 評価(その2)
    							r = kyori(self.n_city, self.seq_w1, self.rg)
    	
    							if r < max :
    								max = r
    								sw  = 1
    								for i3 in range(0, self.n_city) :
    									self.seq_w2[i3] = self.seq_w1[i3]
    								if self.sel > 0 :
    									ch = 1
    									   # 入れ替え(その3)
    							self.seq_w1[0] = self.seq[n3]
    							k              = 1
    							for i4 in range(i2+1, k1+1) :
    								self.seq_w1[k] = self.seq[i4]
    								k += 1
    	
    							for i4 in range(i2, n3, -1) :
    								self.seq_w1[k] = self.seq[i4]
    								k += 1
    	
    							nn = k2
    							while nn != n3 :
    								self.seq_w1[k] = self.seq[nn]
    								k  += 1
    								nn += 1
    								if nn > self.n_city-1 :
    									nn = 0
    									   # 評価(その3)
    							r = kyori(self.n_city, self.seq_w1, self.rg)
    	
    							if r < max :
    								max = r
    								sw  = 1
    								for i3 in range(0, self.n_city) :
    									self.seq_w2[i3] = self.seq_w1[i3]
    								if self.sel > 0 :
    									ch = 1
    									   # 入れ替え(その4)
    							self.seq_w1[0] = self.seq[n3]
    							k              = 1
    							for i4 in range(i2+1, k1+1) :
    								self.seq_w1[k] = self.seq[i4]
    								k += 1
    	
    							for i4 in range(n3+1, i2+1) :
    								self.seq_w1[k] = self.seq[i4]
    								k += 1
    	
    							nn = k2
    							while nn != n3 :
    								self.seq_w1[k] = self.seq[nn]
    								k  += 1
    								nn += 1
    								if nn > self.n_city-1 :
    									nn = 0
    									   # 評価(その4)
    							r = kyori(self.n_city, self.seq_w1, self.rg)
    	
    							if r < max :
    								max = r
    								sw  = 1
    								for i3 in range(0, self.n_city) :
    									self.seq_w2[i3] = self.seq_w1[i3]
    								if self.sel > 0 :
    									ch = 1
    							i3 += 1
    						i2 += 1
    	
    					n3 += 1
    					if n3 > self.n_city-3 :
    						n3 = 0
    					i1 += 1
    							 # 設定
    		if sw > 0 :
    			r_m[0] = max
    			for i1 in range(0, self.n_city) :
    				self.seq[i1] = self.seq_w2[i1]
    	
    		return sw
    	
    #########################
    # クラスPartitionの定義
    #########################
    
    class Partition :
    
    	##########################
    	# コンストラクタ
    	#      name : ファイル名
    	##########################
    
    	def __init__(self, name) :
    	
    		max = 0
    						# ファイルのオープン
    		self.i_file = name   # 入力ファイル名
    		inn         = open(name, "r")
    						# 基本データ
    		s           = inn.readline().split()
    		self.n_city = int(s[1])   # 都市の数
    		self.sel    = int(s[3])   # エッジの選択方法
    		                          #   =0 : 最良のものを選択
    		                          #   =1 : 最初のものを選択
    		self.neib   = int(s[5])   # 近傍(2 or 3)
    		self.seisu  = int(s[7])   # 位置データの表現方法
    		                          #   =1 : 整数
    		                          #   =-1 : 実数(距離を整数計算)
    		                          #   =-2 : 実数(距離を実数計算)
    		s           = inn.readline().split()
    		self.out_m  = int(s[1])   # 出力方法
    		                          #   =-1 : ディスプレイ(経路長だけ)
    		                          #   =0 : ディスプレイ
    		                          #   =1 : ファイル
    		                          #   =2 : ファイル(経路長だけ)
    		self.o_file = ""
    		if self.out_m > 0 :
    			self.o_file = s[3]
    		s            = inn.readline().split()
    		self.n_p_x   = int(s[2])   # x軸方向の分割数
    		self.n_p_y   = int(s[4])   # y軸方向の分割数
    		self.max_try = int(s[6])   # 最大試行回数
    	
    		self.fix = 1   # =1 : 近傍を固定
    		               # =0 : 近傍を可変
    		if self.neib < 0 :
    			self.neib = -self.neib
    			self.fix  = 0
    						# 都市の位置データ
    		self.city = np.empty((self.n_city, 2), np.float)
    		for i1 in range(0, self.n_city) :
    			s                = inn.readline().split()
    			self.city[i1][0] = float(s[0])
    			self.city[i1][1] = float(s[1])
    						# ファイルのクローズ
    		inn.close()
    						# 距離テーブルの作成
    		self.rg = np.empty((self.n_city, self.n_city), np.float)   # 都市間の距離
    
    		for i1 in range(0, self.n_city) :
    			for i2 in range(i1+1, self.n_city) :
    				x = self.city[i2][0] - self.city[i1][0]
    				y = self.city[i2][1] - self.city[i1][1]
    				self.rg[i1][i2] = sqrt(x * x + y * y)
    				if self.seisu > -2 :
    					self.rg[i1][i2] = floor(rg[i1][i2] + 0.5)
    	
    		for i1 in range(0, self.n_city) :
    			for i2 in range(0, i1) :
    				self.rg[i1][i2] = self.rg[i2][i1]
    						# 作業領域
    		self.state  = np.empty((self.n_p_y, self.n_p_x), np.int)   # 領域結合用ワーク
    		self.n_seq  = np.empty((self.n_p_y, self.n_p_x), np.int)   # 各領域の都市数
    		self.n_seq1 = np.empty((self.n_p_y, self.n_p_x), np.int)   # 各領域の都市数(ワーク)
    		self.seq_w1 = np.zeros(self.n_city, np.int)   # 作業領域
    		self.seq_w2 = np.empty(self.n_city, np.int)   # 作業領域
    		self.p_x    = np.empty(self.n_p_x, np.float)   # x軸の分割点
    		self.p_y    = np.empty(self.n_p_y, np.float)   # y軸の分割点
    						# 都市の分割
    		min_x = self.city[0][0]
    		max_x = self.city[0][0]
    		min_y = self.city[0][1]
    		max_y = self.city[0][1]
    	
    		for i1 in range(1, self.n_city) :
    			if self.city[i1][0] < min_x :
    				min_x = self.city[i1][0]
    			else :
    				if self.city[i1][0] > max_x :
    					max_x = self.city[i1][0]
    			if self.city[i1][1] < min_y :
    				min_y = self.city[i1][1]
    			else :
    				if self.city[i1][1] > max_y :
    					max_y = self.city[i1][1]
    	
    		s_x                    = (max_x - min_x) / self.n_p_x
    		self.p_x[0]            = min_x + s_x
    		self.p_x[self.n_p_x-1] = max_x
    		for i1 in range(1, self.n_p_x-1) :
    			self.p_x[i1] = self.p_x[0] + i1 * s_x
    	
    		s_y                    = (max_y - min_y) / self.n_p_y
    		self.p_y[0]            = min_y + s_y
    		self.p_y[self.n_p_y-1] = max_y
    		for i1 in range(1, self.n_p_y-1) :
    			self.p_y[i1] = self.p_y[0] + i1 * s_y
    	
    		self.seq  = np.empty((self.n_p_y, self.n_p_x, self.n_city), np.int)   # 経路
    		self.seq1 = np.empty((self.n_p_y, self.n_p_x, self.n_city), np.int)   # 経路(ワーク)
    		for i1 in range(0, self.n_p_y) :
    			for i2 in range(0, self.n_p_x) :
    				n = 0
    				for i3 in range(0, self.n_city) :
    					if self.seq_w1[i3] == 0 :
    						if self.city[i3][0] <= self.p_x[i2] and self.city[i3][1] <= self.p_y[i1] :
    							self.seq_w1[i3] = 1
    							self.seq_w2[n]  = i3
    							n += 1
    				self.n_seq1[i1][i2] = n
    				if n > 0 :
    					for i3 in range(0, n) :
    						self.seq1[i1][i2][i3] = self.seq_w2[i3]
    					if n > max :
    						max = n
    						# 作業領域
    		print("最大都市数 " + str(max))
    		self.city_i = np.empty((max, 2), np.float)   # 都市の位置データ(作業領域)
    		self.Max    = 0   # 最適経路の長さ
    	
    	##################
    	# 最適化の実行
    	##################
    
    	def Optimize(self) :
    	
    		r = 0
    						# 分割数と開始時間の出力
    		if self.out_m > 0 :
    			self.Output(0, r)
    	
    		for i1 in range(0, self.n_p_y) :
    			for i2 in range(0, self.n_p_x) :
    				self.n_seq[i1][i2] = self.n_seq1[i1][i2]
    				for i3 in range(0, self.n_seq1[i1][i2]) :
    					self.seq[i1][i2][i3] = self.seq1[i1][i2][i3]
    						# 分割毎の最適化
    		for i1 in range(0, self.n_p_y) :
    			for i2 in range(0, self.n_p_x) :
    				if self.n_seq[i1][i2] > 3 :
    							# 近傍の大きさ
    					if self.n_seq[i1][i2] > 3 :
    						nb = self.neib
    					else :
    						nb = 2
    							# 都市位置データの設定
    					for i3 in range(0, self.n_seq[i1][i2]) :
    						k                  = self.seq[i1][i2][i3]
    						self.city_i[i3][0] = self.city[k][0]
    						self.city_i[i3][1] = self.city[k][1]
    							# 最適化
    					it  = Iteration(self.n_seq[i1][i2], self.max_try, self.seisu, self.sel, nb, self.fix, 0, -1, 0, self.o_file, self.city_i)
    					max = it.Optimize()
    							# 結果の保存
    					for i3 in range(0, self.n_seq[i1][i2]) :
    						k               = it.seq[i3]
    						self.seq_w1[i3] = self.seq[i1][i2][k]
    					for i3 in range(0, self.n_seq[i1][i2]) :
    						self.seq[i1][i2][i3] = self.seq_w1[i3]
    							# 出力
    					if self.seisu > -2 :
    						r = int(kyori(self.n_seq[i1][i2], self.seq[i1][i2], self.rg))
    					else :
    						r = floor(kyori(self.n_seq[i1][i2], self.seq[i1][i2], self.rg) + 0.5)
    					print("   y " + str(i1+1) + " x " + str(i2+1) + " n_city " + str(self.n_seq[i1][i2]) + " range " + str(r) + " (trial " + str(max) + ")")
    						# 経路の接続
    		r = self.Connect()
    						# 出力
    		self.Output(self.n_city, r)
    	
    	########################
    	# 出力
    	#      n_c : 都市の数
    	#      r : 距離
    	########################
    
    	def Output(self, n_c, r) :
    	
    		k = 0
    	
    		if self.out_m <= 0 :
    			out = sys.stdout
    			print("距離 " + str(r))
    			input("")
    		else :
    			now = datetime.today().time().isoformat()
    			out = open(self.o_file, "a")
    			if n_c > 0 :
    				print("距離 " + str(r))
    				out.write("   距離 " + str(r) + " 時間 " + now + "\n")
    			else :
    				out.write("問題 " + self.i_file + " 分割 " + str(self.n_p_x) + " " + str(self.n_p_y) + " 時間 " + now + "\n")
    	
    		if n_c > 0 and (self.out_m == 0 or self.out_m == 1) :
    			for i1 in range(0, n_c) :
    				n = self.seq_w1[i1]
    				if self.seisu > 0 :
    					out.write("  " + str(n) + " " + str(int(self.city[n][0])) + " " + str(int(self.city[n][1])) + "\n")
    				else :
    					out.write("  " + str(n) + " " + str(self.city[n][0]) + " " + str(self.city[n][1]) + "\n")
    				if self.out_m == 0 :
    					k += 1
    					if k == 10 :
    						input("")
    						k = 0
    	
    		if self.out_m > 0 :
    			out.close()
    	
    	########################
    	# 分割された領域の接続
    	########################
    
    	def Connect(self) :
    	
    		min   = 0
    		k1    = 0
    		k2    = 0
    		k3    = 0
    		k4    = 0
    		min_c = 0
    		r1    = 0
    		r2    = 0
    		r3    = 0
    		r4    = 0
    		s1    = 0
    		s2    = 0
    		sw    = 1
    				# 領域が1つの場合
    		if self.n_p_x == 1 and self.n_p_y == 1 :
    			for i1 in range(0, self.n_seq[0][0]) :
    				self.seq_w1[i1] = self.seq[0][0][i1]
    				# 初期設定
    		else :
    	
    			for i1 in range(0, self.n_p_y) :
    				for i2 in range(0, self.n_p_x) :
    					if self.n_seq[i1][i2] > 0 :
    						self.state[i1][i2] = 0
    					else :
    						self.state[i1][i2] = 1
    				# 実行
    			while sw > 0 :
    						# 最小節点領域
    				min_c = self.n_city
    				sw    = 0
    				for i1 in range(0, self.n_p_y) :
    					for i2 in range(0, self.n_p_x) :
    						if self.state[i1][i2] == 0 and self.n_seq[i1][i2] < min_c :
    							sw    = 1
    							r1    = i1
    							r2    = i2
    							min_c = self.n_seq[i1][i2]
    						# 結合する対象領域の決定
    				if sw > 0 :
    					sw = 0
    					for i1 in range(0, self.n_p_y) :
    						for i2 in range(0, self.n_p_x) :
    							if self.state[i1][i2] == 0 and (i1 != r1 or i2 != r2) :
    									# 節点の数>2
    								if self.n_seq[r1][r2] > 1 :
    									for i3 in range(0, self.n_seq[r1][r2]) :
    										k1  = self.seq[r1][r2][i3]
    										if i3 == self.n_seq[r1][r2]-1 :
    											k2 = self.seq[r1][r2][0]
    										else :
    											k2 = self.seq[r1][r2][i3+1]
    										wd1 = self.rg[k1][k2]
    										for i4 in range(0, self.n_seq[i1][i2]) :
    											k3  = self.seq[i1][i2][i4]
    											if i4 == self.n_seq[i1][i2]-1 :
    												k4 = self.seq[i1][i2][0]
    											else :
    												k4 = self.seq[i1][i2][i4+1]
    											wd  = wd1 + self.rg[k3][k4]
    											wa1 = self.rg[k1][k3] + self.rg[k2][k4]
    											wa2 = self.rg[k1][k4] + self.rg[k2][k3]
    											if sw == 0 or wa1-wd < min :
    												min = wa1 - wd
    												r3  = i1
    												r4  = i2
    												if i3 == self.n_seq[r1][r2]-1 :
    													s1 = 0
    												else :
    													s1 = i3 + 1
    												if i4 == self.n_seq[i1][i2]-1 :
    													s2 = 0
    												else :
    													s2 = i4 + 1
    												sw = -1
    											if sw == 0 or wa2-wd < min :
    												min = wa2 - wd
    												r3  = i1
    												r4  = i2
    												s1  = i3
    												if i4 == self.n_seq[i1][i2]-1 :
    													s2 = 0
    												else :
    													s2 = i4 + 1
    												sw = 1
    									# 節点の数=1
    								else :
    									k1 = self.seq[r1][r2][0]
    									if self.n_seq[i1][i2] > 1 :
    										for i4 in range(0, self.n_seq[i1][i2]) :
    											k3  = self.seq[i1][i2][i4]
    											if i4 == self.n_seq[i1][i2]-1 :
    												k4 = self.seq[i1][i2][0]
    											else :
    												k4 = self.seq[i1][i2][i4+1]
    											wd  = self.rg[k3][k4]
    											wa1 = self.rg[k1][k3] + self.rg[k1][k4]
    											if sw == 0 or wa1-wd < min :
    												min = wa1 - wd
    												r3  = i1
    												r4  = i2
    												s1  = 0
    												if i4 == self.n_seq[i1][i2]-1 :
    													s2 = 0
    												else :
    													s2 = i4 + 1
    												sw = 1
    									else :
    										k3  = self.seq[i1][i2][0]
    										wa1 = self.rg[k1][k3]
    										if sw == 0 or wa1 < min :
    											min = wa1
    											r3  = i1
    											r4  = i2
    											s1  = 0
    											s2  = 0
    											sw  = 1
    						# 領域の結合
    					self.seq_w1[0] = self.seq[r1][r2][s1]
    					k              = 1
    					n              = s2
    					for i1 in range(0, self.n_seq[r3][r4]) :
    						self.seq_w1[k] = self.seq[r3][r4][n]
    						k += 1
    						n += 1
    						if n > self.n_seq[r3][r4]-1 :
    							n = 0
    					if sw > 0 :
    						n = s1 + 1
    						for i1 in range(0, self.n_seq[r1][r2]-1) :
    							if n > self.n_seq[r1][r2]-1 :
    								n = 0
    							self.seq_w1[k] = self.seq[r1][r2][n]
    							k += 1
    							n += 1
    					else :
    						n = s1 - 1
    						for i1 in range(0, self.n_seq[r1][r2]-1) :
    							if n < 0 :
    								n = self.n_seq[r1][r2] - 1
    							self.seq_w1[k] = self.seq[r1][r2][n]
    							k += 1
    							n -= 1
    						# 状態の変更
    					self.n_seq[r1][r2] += self.n_seq[r3][r4]
    					self.state[r3][r4]  = 1
    					for i1 in range(0, self.n_seq[r1][r2]) :
    						self.seq[r1][r2][i1] = self.seq_w1[i1]
    					sw = 1
    	
    		if self.seisu > -2 :
    			r = int(kyori(self.n_city, self.seq_w1, self.rg))
    		else :
    			r = floor(kyori(self.n_city, self.seq_w1, self.rg) + 0.5)
    		self.Max = r
    	
    		return r
    
    ################################
    # 巡回セールスマン問題(分割法)
    #      coded by Y.Suganuma
    ################################
    
    				# 入力ミス
    if len(sys.argv) <= 1 :
    	print("***error  ファイル名を入力して下さい")
    				# 入力OK
    else :
    					# ファイルのオープン
    	inn = open(sys.argv[1], "r")
    					# 問題数と入力データファイル名
    	s   = inn.readline().split()
    	nm  = int(s[1])
    
    	for i0 in range(0, nm) :
    						# 各問題の実行
    		s      = inn.readline().split()
    		i_file = s[1]
    		n      = int(s[3])
    		pt     = Partition(i_file)
    		mean   = 0.0
    		max    = -1
    							# 乱数の初期値を変える
    		for i1 in range(0, n) :
    			print("\n+++++問題 " + i_file + " +++++")
    			seed(1000 * i1 + 1234567);
    								# 最適化
    			pt.Optimize()
    								# 最適値とその平均の計算
    			mean += pt.Max
    			if max < 0 or pt.Max < max :
    				max = pt.Max
    						# 結果
    		if pt.out_m <= 0 :
    			print("     -----最小 " + str(max) + " 平均 " + str(mean/n) + "-----")
    		else :
    			out = open(pt.o_file, "a")
    			out.write("     -----最小 " + str(max) + " 平均 " + str(mean/n) + "-----\n")
    			out.close()
    
    	inn.close()
    
    """
    ------------------------ケーススタディデータ(data.txt)------
    問題の数 2
    問題 data1.txt 繰り返し回数 2
    問題 data2.txt 繰り返し回数 1
    
    ---------------------データファイル(data1.txt)------------
    都市の数 50 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 2 Y 2 最大試行回数 1000
    86.950684 27.711487
    82.357788 16.148376
    29.791260 37.959290
    27.493286 1.542664
    90.893555 88.734436
    40.109253 92.308044
    87.445068 53.474426
    24.893188 99.382019
    11.633301 80.616760
    61.532593 8.702087
    30.645752 93.598938
    4.714966 81.205750
    86.669922 90.858459
    84.127808 52.830505
    96.893311 45.832825
    4.458618 34.513855
    53.503418 6.959534
    45.394897 12.193298
    23.687744 97.676086
    61.624146 46.806335
    49.633789 16.419983
    82.833862 74.290466
    48.529053 36.628723
    13.711548 5.583191
    12.561035 6.739807
    33.944702 26.622009
    8.917236 50.190735
    98.220825 98.344421
    79.785156 65.419006
    36.227417 56.687927
    42.352295 25.862122
    52.651978 12.590027
    88.806152 79.957581
    27.182007 51.988220
    86.334229 51.142883
    14.505005 35.820007
    77.124023 37.855530
    44.308472 0.022888
    78.363037 13.533020
    21.279907 55.534363
    82.238770 26.612854
    25.106812 88.291931
    55.938721 0.532532
    10.476685 59.233093
    41.650391 33.729553
    7.077026 4.295349
    56.561279 99.641418
    19.595337 34.416199
    92.858887 46.705627
    27.719116 35.533142
    
    ---------------------データファイル(data2.txt)------------
    都市の数 10 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 1 Y 1 最大試行回数 1000
    8.695068 2.771149
    8.235779 1.614838
    2.979126 3.795929
    2.749329 0.154266
    9.089355 8.873444
    4.010925 9.230804
    8.744507 5.347443
    2.489319 9.938202
    1.163330 8.061676
    6.153259 0.870209
    """
    			

  6. C#

    /****************************/
    /* 巡回セールスマン問題     */
    /* (分割法)               */
    /*      coded by Y.Suganuma */
    /****************************/
    using System;
    using System.IO;
    
    /*************************/
    /* クラスPartitionの定義 */
    /*************************/
    class Partition {
    	float [][] rg;   // 都市間の距離
    	float [] p_x;   // x軸の分割点
    	float [] p_y;   // y軸の分割点
    	int fix;   // =1 : 近傍を固定
                   // =0 : 近傍を可変
    	int max_try;   // 最大試行回数
    	int [] seq_w1;   // 作業領域
    	int [] seq_w2;   // 作業領域
    	int neib;   // 近傍(2 or 3)
    	public int seisu;   // 位置データの表現方法
                            //   =1 : 整数
                            //   =-1 : 実数(距離を整数計算)
                            //   =-2 : 実数(距離を実数計算)
    	int sel;   // エッジの選択方法
                   //   =0 : 最良のものを選択
                   //   =1 : 最初のものを選択
    	Random rn;   // 乱数
    
    	float [][] city;   //都市の位置データ
    	float [][] city_i;   //都市の位置データ(作業領域)
    	public int Max;   // 最適経路の長さ
    	int n_city;   // 都市の数
    	int [][] n_seq;   // 各領域の都市数
    	int [][] n_seq1;   // 各領域の都市数(ワーク)
    	int n_p_x;   // x軸方向の分割数
    	int n_p_y;   // y軸方向の分割数
    	public int out_m;   // 出力方法
                     //   =-1 : ディスプレイ(経路長だけ)
                     //   =0 : ディスプレイ
                     //   =1 : ファイル
                     //   =2 : ファイル(経路長だけ)
    	int range;   // 現在の評価値
    	int seed;   // 乱数の初期値
    	int [][][] seq;   // 経路
    	int [][][] seq1;   // 経路(ワーク)
    	int [][] state;   // 領域結合用ワーク
    	public String o_file;   // 出力ファイル名
    	String i_file;   // 入力ファイル名
    
    	/****************************/
    	/* コンストラクタ           */
    	/*      i_file : ファイル名 */
    	/****************************/
    	public Partition (String name)
    	{
    		i_file         = name;
    		string[] lines = File.ReadAllLines(i_file);
    					// 基本データ
    						// 1行目
    		string[] str = lines[0].Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
    		n_city       = int.Parse(str[1]);
    		sel          = int.Parse(str[3]);
    		neib         = int.Parse(str[5]);
    		seisu        = int.Parse(str[7]);
    		if (neib < 0) {
    			neib = -neib;
    			fix  = 0;
    		}
    		else
    			fix = 1;
    						// 2行目
    		str    = lines[1].Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
    		out_m  = int.Parse(str[1]);
    		o_file = str[3];
    						// 3行目
    		str     = lines[2].Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
    		n_p_x   = int.Parse(str[2]);
    		n_p_y   = int.Parse(str[4]);
    		max_try = int.Parse(str[6]);
    					// 都市の位置データ
    		city = new float [n_city][];
    		for (int i1 = 0; i1 < n_city; i1++) {
    			city[i1]    = new float [2];
    			str         = lines[i1+3].Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
    			city[i1][0] = float.Parse(str[0]);
    			city[i1][1] = float.Parse(str[1]);
    		}
    					// 距離テーブルの作成
    		rg = new float [n_city][];
    
    		for (int i1 = 0; i1 < n_city; i1++) {
    			rg[i1] = new float [n_city];
    			for (int i2 = i1+1; i2 < n_city; i2++) {
    				double x   = city[i2][0] - city[i1][0];
    				double y   = city[i2][1] - city[i1][1];
    				rg[i1][i2] = (float)Math.Sqrt(x * x + y * y);
    				if (seisu > -2)
    					rg[i1][i2] = (int)(rg[i1][i2] + 0.5);
    			}
    		}
    
    		for (int i1 = 1; i1 < n_city; i1++) {
    			for (int i2 = 0; i2 < i1; i2++)
    				rg[i1][i2] = rg[i2][i1];
    		}
    					// 作業領域
    		state  = new int [n_p_y][];
    		n_seq  = new int [n_p_y][];
    		n_seq1 = new int [n_p_y][];
    		for (int i1 = 0; i1 < n_p_y; i1++) {
    			state[i1]  = new int [n_p_x];
    			n_seq[i1]  = new int [n_p_x];
    			n_seq1[i1] = new int [n_p_x];
    		}
    
    		seq    = new int [n_p_y][][];
    		seq1   = new int [n_p_y][][];
    		for (int i1 = 0; i1 < n_p_y; i1++) {
    			seq[i1]    = new int [n_p_x][];
    			seq1[i1]   = new int [n_p_x][];
    			for (int i2 = 0; i2 < n_p_x; i2++) {
    				seq[i1][i2]    = new int [n_city];
    				seq1[i1][i2]   = new int [n_city];
    			}
    		}
    
    		seq_w1 = new int [n_city];
    		seq_w2 = new int [n_city];
    		p_x    = new float [n_p_x];
    		p_y    = new float [n_p_y];
    					// 都市の分割
    		for (int i1 = 0; i1 < n_city; i1++)
    			seq_w1[i1] = 0;
    
    		float min_x = city[0][0];
    		float max_x = city[0][0];
    		float min_y = city[0][1];
    		float max_y = city[0][1];
    
    		for (int i1 = 1; i1 < n_city; i1++) {
    			if (city[i1][0] < min_x)
    				min_x = city[i1][0];
    			else {
    				if (city[i1][0] > max_x)
    					max_x = city[i1][0];
    			}
    			if (city[i1][1] < min_y)
    				min_y = city[i1][1];
    			else {
    				if (city[i1][1] > max_y)
    					max_y = city[i1][1];
    			}
    		}
    
    		float s_x    = (max_x - min_x) / n_p_x;
    		p_x[0]       = min_x + s_x;
    		p_x[n_p_x-1] = max_x;
    		for (int i1 = 1; i1 < n_p_x-1; i1++)
    			p_x[i1] = p_x[0] + i1 * s_x;
    
    		float s_y    = (max_y - min_y) / n_p_y;
    		p_y[0]       = min_y + s_y;
    		p_y[n_p_y-1] = max_y;
    		for (int i1 = 1; i1 < n_p_y-1; i1++)
    			p_y[i1] = p_y[0] + i1 * s_y;
    
    		int max = 0;
    		for (int i1 = 0; i1 < n_p_y; i1++) {
    			for (int i2 = 0; i2 < n_p_x; i2++) {
    				int n = 0;
    				for (int i3 = 0; i3 < n_city; i3++) {
    					if (seq_w1[i3] == 0) {
    						if (city[i3][0] <= p_x[i2] && city[i3][1] <= p_y[i1]) {
    							seq_w1[i3] = 1;
    							seq_w2[n]  = i3;
    							n++;
    						}
    					}
    				}
    				n_seq1[i1][i2] = n;
    				if (n > 0) {
    					for (int i3 = 0; i3 < n; i3++)
    						seq1[i1][i2][i3] = seq_w2[i3];
    					if (n > max)
    						max = n;
    				}
    			}
    		}
    
    		for (int i1 = 0; i1 < n_p_y; i1++) {
    			for (int i2 = 0; i2 < n_p_x; i2++)
    				state[i1][i2] = (n_seq1[i1][i2] > 0) ? 0 : 1;
    		}
    					// 作業領域
    		Console.WriteLine("最大都市数 " + max);
    		city_i = new float [max][];
    		for (int i1 = 0; i1 < max; i1++)
    			city_i[i1] = new float [2];
    	}
    
    	/******************************/
    	/* 最適化の実行               */
    	/*      seed_i : 乱数の初期値 */
    	/******************************/
    	public void Optimize(int seed_i)
    	{
    					// 乱数の初期設定
    		seed = seed_i;
    		rn   = new Random (seed);   // rn.NextDouble();
    
    		for (int i1 = 0; i1 < n_p_y; i1++) {
    			for (int i2 = 0; i2 < n_p_x; i2++) {
    				n_seq[i1][i2] = n_seq1[i1][i2];
    				state[i1][i2] = (n_seq1[i1][i2] > 0) ? 0 : 1;
    				for (int i3 = 0; i3 < n_seq1[i1][i2]; i3++)
    					seq[i1][i2][i3] = seq1[i1][i2][i3];
    			}
    		}
    						// 分割数と開始時間の出力(ファイルへ出力する場合)
    		if (out_m > 0)
    			Output(0);
    						// 分割毎の最適化
    		for (int i1 = 0; i1 < n_p_y; i1++) {
    			for (int i2 = 0; i2 < n_p_x; i2++) {
    				if (n_seq[i1][i2] > 3) {
    							// 近傍の大きさ
    					int nb = (n_seq[i1][i2] > 3) ? neib : 2;
    							// 都市位置データの設定
    					for (int i3 = 0; i3 < n_seq[i1][i2]; i3++) {
    						int k         = seq[i1][i2][i3];
    						city_i[i3][0] = city[k][0];
    						city_i[i3][1] = city[k][1];
    					}
    							// 最適化
    					Iteration it  = new Iteration (n_seq[i1][i2], max_try, seisu,
    					                               sel, nb, fix, 0, -1, 0, o_file,
    					                               city_i, rn);
    					int max = it.Optimize();
    							// 結果の保存
    					for (int i3 = 0; i3 < n_seq[i1][i2]; i3++) {
    						int k      = it.seq[i3];
    						seq_w1[i3] = seq[i1][i2][k];
    					}
    					for (int i3 = 0; i3 < n_seq[i1][i2]; i3++)
    						seq[i1][i2][i3] = seq_w1[i3];
    							// 出力(文字)
    					int r = (seisu > -2) ? 
    					        (int)Iteration.kyori(n_seq[i1][i2], seq[i1][i2], rg) :
    					        (int)(Iteration.kyori(n_seq[i1][i2], seq[i1][i2], rg) + 0.5);
    					Console.WriteLine("   y " + (i1+1) + " x " + (i2+1) +
                                         " n_city " + n_seq[i1][i2] +
                                         " range " + r + " (trial " + max + ")");
    				}
    			}
    		}
    						// 経路の接続
    		range = Connect();
    		Max   = range;
    						// 出力(文字)
    		Output(n_city);
    	}
    
    	/***********************/
    	/* 出力                */
    	/*      n_c : 都市の数 */
    	/***********************/
    	void Output(int n_c)
    	{
    		StreamWriter OUT = new StreamWriter(o_file, true);
    		if (out_m <= 0) {
    			Console.WriteLine("距離 " + range);
    			Console.ReadLine();
    		}
    		else {
    			DateTime now = DateTime.Now;   // 現在時刻の獲得
    			if (n_c > 0) {
    				Console.WriteLine("距離 " + range);
    				OUT.WriteLine("   距離 " + range + " 時間 " + now);
    			}
    			else
    				OUT.WriteLine("問題 " + i_file + " 乱数 " + seed + " 分割 " + n_p_x +
    				              " " + n_p_y + " 時間 " + now);
    		}
    
    		int k = 0;
    		if (n_c > 0 && (out_m == 0 || out_m == 1)) {
    			for (int i1 = 0; i1 < n_c; i1++) {
    				int n = seq_w1[i1];
    				if (out_m > 0) {
    					if (seisu > 0)
    						OUT.WriteLine("  " + n + " " + (int)city[n][0] + " " + (int)city[n][1]);
    					else
    						OUT.WriteLine("  " + n + " " + city[n][0] + " " + city[n][1]);
    				}
    				else {
    					if (seisu > 0)
    						Console.WriteLine("  " + n + " " + (int)city[n][0] + " " + (int)city[n][1]);
    					else
    						Console.WriteLine("  " + n + " " + city[n][0] + " " + city[n][1]);
    				}
    				if (out_m == 0) {
    					k++;
    					if (k == 10) {
    						Console.ReadLine();
    						k = 0;
    					}
    				}
    			}
    		}
    
    		OUT.Close();
    	}
    
    	/************************/
    	/* 分割された領域の接続 */
    	/************************/
    	int Connect()
    	{
    		double wd, wd1, wa1, wa2, min = 0;
    		int i1, i2, i3, i4, k, k1 = 0, k2 = 0, k3 = 0, k4 = 0, min_c = 0, n, r,
                r1 = 0, r2 = 0, r3 = 0, r4 = 0, s1 = 0, s2 = 0, sw = 1;
    	/*
    	     領域が1つの場合
    	*/
    		if (n_p_x == 1 && n_p_y == 1) {
    			for (i1 = 0; i1 < n_seq[0][0]; i1++)
    				seq_w1[i1] = seq[0][0][i1];
    		}
    	/*
    	     領域が複数の場合
    	*/
    		else {
    
    			while (sw > 0) {
    						// 最小節点領域
    				min_c = n_city;
    				sw    = 0;
    				for (i1 = 0; i1 < n_p_y; i1++) {
    					for (i2 = 0; i2 < n_p_x; i2++) {
    						if (state[i1][i2] == 0 && n_seq[i1][i2] < min_c) {
    							sw    = 1;
    							r1    = i1;
    							r2    = i2;
    							min_c = n_seq[i1][i2];
    						}
    					}
    				}
    						// 結合する対象領域の決定
    				if (sw > 0) {
    					sw = 0;
    					for (i1 = 0; i1 < n_p_y; i1++) {
    						for (i2 = 0; i2 < n_p_x; i2++) {
    							if (state[i1][i2] == 0 && (i1 != r1 || i2 != r2)) {
    									// 節点の数>2
    								if (n_seq[r1][r2] > 1) {
    									for (i3 = 0; i3 < n_seq[r1][r2]; i3++) {
    										k1  = seq[r1][r2][i3];
    										k2  = (i3 == n_seq[r1][r2]-1) ? seq[r1][r2][0] :
                                                                            seq[r1][r2][i3+1];
    										wd1 = rg[k1][k2];
    										for (i4 = 0; i4 < n_seq[i1][i2]; i4++) {
    											k3  = seq[i1][i2][i4];
    											k4  = (i4 == n_seq[i1][i2]-1) ? seq[i1][i2][0] :
                                                                                seq[i1][i2][i4+1];
    											wd  = wd1 + rg[k3][k4];
    											wa1 = rg[k1][k3] + rg[k2][k4];
    											wa2 = rg[k1][k4] + rg[k2][k3];
    											if (sw == 0 || wa1-wd < min) {
    												min = wa1 - wd;
    												r3  = i1;
    												r4  = i2;
    												s1  = (i3 == n_seq[r1][r2]-1) ? 0 : i3 + 1;
    												s2  = (i4 == n_seq[i1][i2]-1) ? 0 : i4 + 1;
    												sw  = -1;
    											}
    											if (sw == 0 || wa2-wd < min) {
    												min = wa2 - wd;
    												r3  = i1;
    												r4  = i2;
    												s1  = i3;
    												s2  = (i4 == n_seq[i1][i2]-1) ? 0 : i4 + 1;
    												sw  = 1;
    											}
    										}
    									}
    								}
    									// 節点の数=1
    								else {
    									k1 = seq[r1][r2][0];
    									if (n_seq[i1][i2] > 1) {
    										for (i4 = 0; i4 < n_seq[i1][i2]; i4++) {
    											k3  = seq[i1][i2][i4];
    											k4  = (i4 == n_seq[i1][i2]-1) ? seq[i1][i2][0] :
                                                                                seq[i1][i2][i4+1];
    											wd  = rg[k3][k4];
    											wa1 = rg[k1][k3] + rg[k1][k4];
    											if (sw == 0 || wa1-wd < min) {
    												min = wa1 - wd;
    												r3  = i1;
    												r4  = i2;
    												s1  = 0;
    												s2  = (i4 == n_seq[i1][i2]-1) ? 0 : i4 + 1;
    												sw  = 1;
    											}
    										}
    									}
    									else {
    										k3  = seq[i1][i2][0];
    										wa1 = rg[k1][k3];
    										if (sw == 0 || wa1 < min) {
    											min = wa1;
    											r3  = i1;
    											r4  = i2;
    											s1  = 0;
    											s2  = 0;
    											sw  = 1;
    										}
    									}
    								}
    							}
    						}
    					}
    						// 領域の結合
    					seq_w1[0] = seq[r1][r2][s1];
    					k         = 1;
    					n         = s2;
    					for (i1 = 0; i1 < n_seq[r3][r4]; i1++) {
    						seq_w1[k] = seq[r3][r4][n];
    						k++;
    						n++;
    						if (n > n_seq[r3][r4]-1)
    							n = 0;
    					}
    					if (sw > 0) {
    						n = s1 + 1;
    						for (i1 = 0; i1 < n_seq[r1][r2]-1; i1++) {
    							if (n > n_seq[r1][r2]-1)
    								n = 0;
    							seq_w1[k] = seq[r1][r2][n];
    							k++;
    							n++;
    						}
    					}
    					else {
    						n = s1 - 1;
    						for (i1 = 0; i1 < n_seq[r1][r2]-1; i1++) {
    							if (n < 0)
    								n = n_seq[r1][r2] - 1;
    							seq_w1[k] = seq[r1][r2][n];
    							k++;
    							n--;
    						}
    					}
    						// 状態の変更
    					n_seq[r1][r2] += n_seq[r3][r4];
    					state[r3][r4]  = 1;
    					for (i1 = 0; i1 < n_seq[r1][r2]; i1++)
    						seq[r1][r2][i1] = seq_w1[i1];
    					sw  = 1;
    				}
    			}
    		}
    
    		r = (seisu > -2) ? (int)Iteration.kyori(n_city, seq_w1, rg) :
                              (int)(Iteration.kyori(n_city, seq_w1, rg) + 0.5);
    
    		return r;
    	}
    }
    
    /*************************/
    /* クラスIterationの定義 */
    /*************************/
    class Iteration {
    	float [][] rg;   // 都市間の距離
    	int fix;   // =1 : 近傍を固定
                   // =0 : 近傍を可変
    	int max_try;   // 最大試行回数
    	int neib;   // 近傍(2 or 3)
    	int out_d;   // 表示間隔
    	int [] seq_w1;   // 都市を訪れる順序(ワーク)
    	int [] seq_w2;   // 都市を訪れる順序(ワーク)
    	int [] seq_w3;   // 都市を訪れる順序(ワーク)
    	int [] seq_w4;   // 都市を訪れる順序(ワーク)
    	int [] seq_w5;   // 都市を訪れる順序(ワーク)
    	int out_lvl;   // 出力レベル
                       //   =0 : 最終出力だけ
                       //   n>0 : n世代毎に出力(負の時はファイル)
    	int out_m;   // 出力方法
                     //   =-1 : 出力しない
                     //   =0 : すべてを出力
                     //   =1 : 評価値だけを出力(最終結果だけはすべてを出力)
    	int seisu;   // 位置データの表現方法
                     //   =1 : 整数
                     //   =-1 : 実数(距離を整数計算)
                     //   =-2 : 実数(距離を実数計算)
    	int sel;   // エッジの選択方法
                   //   =0 : 最良のものを選択
                   //   =1 : 最初のものを選択
    	String o_file;   // 出力ファイル名
    	Random rn;   // 乱数
    
    	double range;   // 現在の評価値
    	float [][] city;   //都市の位置データ
    	int n_city;   // 都市の数
    	int n_tri;   // 試行回数
    	public int [] seq;   // 都市を訪れる順序
    
    	/**********************************/
    	/* コンストラクタ                 */
    	/*      n_city_i : 都市の数       */
    	/*      max_try_i : 最大試行回数  */
    	/*      sei_i : 整数 or 実数      */
    	/*      sel_i : エッジの選択方法  */
    	/*      neib_i : 近傍(2 or 3)   */
    	/*      fix_i : 近傍の扱い方      */
    	/*      out_lvl_i : 出力レベル    */
    	/*      out_m_i : 出力方法        */
    	/*      out_d_i : 表示間隔        */
    	/*      o_file_i : 出力ファイル名 */
    	/*      city_i : 都市の位置データ */
    	/*      rn_i : 乱数               */
    	/**********************************/
    	public Iteration (int n_city_i, int max_tri_i, int sei_i, int sel_i, int neib_i,
                   int fix_i, int out_lvl_i, int out_m_i, int out_d_i, String o_file_i,
                   float [][] city_i, Random rn_i)
    	{
    						// 値の設定
    		n_city  = n_city_i;
    		max_try = max_tri_i;
    		seisu   = sei_i;
    		sel     = sel_i;
    		neib    = neib_i;
    		fix     = fix_i;
    		out_lvl = out_lvl_i;
    		out_m   = out_m_i;
    		out_d   = out_d_i;
    		o_file  = o_file_i;
    		rn      = rn_i;
    		n_tri   = 0;
    						// 都市の位置データ
    		city = new float [n_city][];
    		for (int i1 = 0; i1 < n_city; i1++) {
    			city[i1]    = new float [2];
    			city[i1][0] = city_i[i1][0];
    			city[i1][1] = city_i[i1][1];
    		}
    						// 距離テーブルの作成
    		rg = new float [n_city][];
    
    		for (int i1 = 0; i1 < n_city; i1++) {
    			rg[i1] = new float [n_city];
    			for (int i2 = i1+1; i2 < n_city; i2++) {
    				double x   = city[i2][0] - city[i1][0];
    				double y   = city[i2][1] - city[i1][1];
    				rg[i1][i2] = (float)Math.Sqrt(x * x + y * y);
    				if (seisu > -2)
    					rg[i1][i2] = (int)(rg[i1][i2] + 0.5);
    			}
    		}
    
    		for (int i1 = 1; i1 < n_city; i1++) {
    			for (int i2 = 0; i2 < i1; i2++)
    				rg[i1][i2] = rg[i2][i1];
    		}
    						// 都市を訪れる順序(初期設定)
    		seq    = new int [n_city];
    		seq_w1 = new int [n_city];
    		seq_w2 = new int [n_city];
    		seq_w3 = new int [n_city];
    		seq_w4 = new int [n_city];
    		seq_w5 = new int [n_city];
    
    		for (int i1 = 0; i1 < n_city; i1++) {
    			int sw = 0;
    			while (sw == 0) {
    				int ct = (int)(rn.NextDouble() * n_city);
    				if (ct >= n_city)
    					ct = n_city - 1;
    				seq[i1] = ct;
    				sw      = 1;
    				for (int i2 = 0; i2 < i1 && sw > 0; i2++) {
    					if (ct == seq[i2])
    						sw = 0;
    				}
    			}
    		}
    	}
    
    	/****************/
    	/* 最適化の実行 */
    	/****************/
    	public int Optimize ()
    	{
    		int sw;
    				// 初期設定
    		range = kyori(n_city, seq, rg);
    				// 初期状態の出力(文字)
    		if (out_m >= 0 && Math.Abs(out_lvl) > 0) {
    			if (seisu > -2)
    				Console.WriteLine("***試行回数 " + n_tri + " 距離 " + (int)range);
    			else
    				Console.WriteLine("***試行回数 " + n_tri + " 距離 " + range);
    			Output(out_lvl);
    		}
    				// 実行
    		sw = 1;
    		for (n_tri = 1; n_tri <= max_try && sw > 0; n_tri++) {
    					// 改善
    			sw = Change();
    							// 出力(文字)
    			if (out_d > 0 && n_tri%out_d == 0) {
    				if (seisu > -2)
    					Console.WriteLine("***試行回数 " + n_tri + " 距離 " + (int)range);
    				else
    					Console.WriteLine("***試行回数 " + n_tri + " 距離 " + range);
    			}
    
    			if (out_m >= 0 && Math.Abs(out_lvl) > 0) {
    				if (n_tri%Math.Abs(out_lvl) == 0)
    					Output(out_lvl);
    			}
    		}
    				// 最終出力(文字)
    		if (out_m >= 0) {
    			n_tri--;
    			if (seisu > -2)
    				Console.WriteLine("***試行回数 " + n_tri + " 距離 " + (int)range);
    			else
    				Console.WriteLine("***試行回数 " + n_tri + " 距離 " + (int)(range+0.5));
    			Output(out_lvl);
    		}
    
    		return n_tri;
    	}
    
    	/*******************************/
    	/* 出力                        */
    	/*      sw : >= 0 : 出力先未定 */
    	/*           < 0 : ファイル    */
    	/*******************************/
    	void Output(int sw)
    	{
    		int pr = -1;
    		if (sw >= 0) {
    			Console.Write("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ");
    			pr = int.Parse(Console.ReadLine());
    		}
    
    		if (pr != 0) {
    
    			StreamWriter OUT = new StreamWriter(o_file, true);
    
    			if (pr < 0) {
    				DateTime now = DateTime.Now;   // 現在時刻の獲得
    				if (seisu > -2)
    					OUT.WriteLine("***試行回数 " + n_tri + " 距離 " + (int)range + " 時間 " + now);
    				else
    					OUT.WriteLine("***試行回数 " + n_tri + " 距離 " + (int)(range+0.5) +
    					               " 時間 " + now);
    			}
    
    			if (out_m == 0) {
    				int k = 0;
    				for (int i1 = 0; i1 < n_city; i1++) {
    					int n = seq[i1];
    					if (pr < 0) {
    						if (seisu > 0)
    							OUT.WriteLine("  " + n + " " + (int)city[n][0] + " " + (int)city[n][1]);
    						else
    							OUT.WriteLine("  " + n + " " + city[n][0] + " " + city[n][1]);
    					}
    					else {
    						if (seisu > 0)
    							Console.WriteLine("  " + n + " " + (int)city[n][0] + " " + (int)city[n][1]);
    						else
    							Console.WriteLine("  " + n + " " + city[n][0] + " " + city[n][1]);
    					}
    					if (pr > 0) {
    						k++;
    						if (k == pr) {
    							Console.ReadLine();
    							k = 0;
    						}
    					}
    				}
    			}
    
    			OUT.Close();
    		}
    	}
    
    	/**************************************/
    	/* エッジの入れ替え                   */
    	/*      return : =0 : 改善がなかった  */
    	/*               =1 : 改善があった    */
    	/**************************************/
    	int Change()
    	{
    		double max, max1 = 0.0, r;
    		int ch = 0, i0, i1, i2, i3, i4, k, k1 = 0, k2 = 0, k3, k4,
                n, nn, n1 = 0, n2 = 0, n3, n4, sw = 0, sw1 = 0, sw2;
    
    		max = range;
    			//
    			// 近傍を可変
    			//
    		if (fix == 0) {
    					// 初期設定(k=2)
    			k = 2;
    			for (i1 = 0; i1 < n_city; i1++) {
    				seq_w4[i1] = seq[i1];
    				seq_w3[i1] = 0;
    			}
    						// 評価
    			sw2 = 0;
    			for (i0 = 0; i0 < n_city-2 && sw2 < 2; i0++) {
    
    				n = (i0 == 0) ? n_city-1 : n_city;
    
    				for (i1 = i0+2; i1 < n && sw2 < 2; i1++) {
    							// 相手の場所
    					k3 = i1;
    					k4 = k3 + 1;
    					if (k4 > n_city-1)
    						k4 = 0;
    							// 順番の入れ替え
    					n3 = -1;
    					for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    						if (seq_w4[i2] == seq[i0+1])
    							n3 = i2 + 1;
    					}
    					nn = n3;
    					n4 = -1;
    					for (i2 = 0; i2 < n_city && n4 < 0; i2++) {
    						if (nn > n_city-1)
    							nn = 0;
    						if (seq_w4[nn] == seq[k3] || seq_w4[nn] == seq[k4])
    							n4 = seq_w4[nn];
    						else
    							nn++;
    					}
    					if (n4 == seq[k4]) {
    						n4 = k3;
    						k3 = k4;
    						k4 = n4;
    					}
    							// 評価
    					seq_w1[0] = seq[k4];
    					seq_w1[1] = seq[i0+1];
    					n4        = -1;
    					nn        = 2;
    					while (n4 < 0) {
    						if (n3 > n_city-1)
    							n3 = 0;
    						seq_w1[nn] = seq_w4[n3];
    						if (seq_w4[n3] == seq[k3])
    							n4 = 1;
    						nn++;
    						n3++;
    					}
    					seq_w1[nn] = seq[i0];
    					nn++;
    					n3 = -1;
    					n4 = -1;
    					for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    						if (seq_w4[i2] == seq[i0]) {
    							n3 = i2 - 1;
    							if (n3 < 0)
    								n3 = n_city - 1;
    						}
    					}
    					while (n4 < 0) {
    						if (seq_w4[n3] == seq[k4])
    							n4 = 1;
    						else {
    							seq_w1[nn] = seq_w4[n3];
    							nn++;
    							n3--;
    							if (n3 < 0)
    								n3 = n_city - 1;
    						}
    					}
    
    					r = kyori(n_city, seq_w1, rg);
    							// 最適値の保存
    					if (sw2 == 0 || r < max1) {
    						sw2  = 1;
    						max1 = r;
    						n1   = k3;
    						n2   = k4;
    						k1   = i0;
    						k2   = i0 + 1;
    						for (i2 = 0; i2 < n_city; i2++)
    							seq_w5[i2] = seq_w1[i2];
    						if (sel > 0 && max1 < max)
    							sw2 = 2;
    					}
    				}
    			}
    						// 最適値の保存と近傍の増加
    			if (sw2 > 0) {
    				if (max1 < max) {
    					sw  = 1;
    					max = max1;
    					for (i1 = 0; i1 < n_city; i1++)
    						seq_w2[i1] = seq_w5[i1];
    				}
    				if (k < neib) {
    					for (i1 = 0; i1 < n_city; i1++)
    						seq_w4[i1] = seq_w5[i1];
    					seq_w3[k1] = 1;
    					seq_w3[k2] = 1;
    					seq_w3[n1] = 1;
    					seq_w3[n2] = 1;
    					k1         = n2;
    					k++;
    				}
    				else
    					sw1 = 1;
    			}
    			else
    				sw1 = 1;
    					// 実行(k>2)
    			while (sw1 == 0) {
    						// 評価
    				sw2 = 0;
    				for (i1 = 0; i1 < n_city; i1++) {
    							// 相手の場所
    					k3 = i1;
    					k4 = k3 + 1;
    					if (k4 > n_city-1)
    						k4 = 0;
    
    					if (seq_w3[k3] == 0 && seq_w3[k4] == 0) {
    							// 順番の入れ替え
    						n3 = -1;
    						for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    							if (seq_w4[i2] == seq[k2])
    								n3 = i2 + 1;
    						}
    						nn = n3;
    						n4 = -1;
    						for (i2 = 0; i2 < n_city && n4 < 0; i2++) {
    							if (nn > n_city-1)
    								nn = 0;
    							if (seq_w4[nn] == seq[k3] || seq_w4[nn] == seq[k4])
    								n4 = seq_w4[nn];
    							else
    								nn++;
    						}
    						if (n4 == seq[k4]) {
    							n4 = k3;
    							k3 = k4;
    							k4 = n4;
    						}
    							// 評価
    						seq_w1[0] = seq[k4];
    						seq_w1[1] = seq[k2];
    						n4        = -1;
    						nn        = 2;
    						while (n4 < 0) {
    							if (n3 > n_city-1)
    								n3 = 0;
    							seq_w1[nn] = seq_w4[n3];
    							if (seq_w4[n3] == seq[k3])
    								n4 = 1;
    							nn++;
    							n3++;
    						}
    						seq_w1[nn] = seq[k1];
    						nn++;
    						n3 = -1;
    						n4 = -1;
    						for (i2 = 0; i2 < n_city && n3 < 0; i2++) {
    							if (seq_w4[i2] == seq[k1]) {
    								n3 = i2 - 1;
    								if (n3 < 0)
    									n3 = n_city - 1;
    							}
    						}
    						while (n4 < 0) {
    							if (seq_w4[n3] == seq[k4])
    								n4 = 1;
    							else {
    								seq_w1[nn] = seq_w4[n3];
    								nn++;
    								n3--;
    								if (n3 < 0)
    									n3 = n_city - 1;
    							}
    						}
    
    						r = kyori(n_city, seq_w1, rg);
    							// 最適値の保存
    						if (sw2 == 0 || r < max1) {
    							sw2  = 1;
    							max1 = r;
    							n1   = k3;
    							n2   = k4;
    							for (i2 = 0; i2 < n_city; i2++)
    								seq_w5[i2] = seq_w1[i2];
    						}
    					}
    				}
    						// 最適値の保存と近傍の増加
    				if (sw2 > 0) {
    					if (max1 < max) {
    						sw  = 1;
    						max = max1;
    						for (i1 = 0; i1 < n_city; i1++)
    							seq_w2[i1] = seq_w5[i1];
    					}
    					if (k < neib) {
    						for (i1 = 0; i1 < n_city; i1++)
    							seq_w4[i1] = seq_w5[i1];
    						seq_w3[n1] = 1;
    						seq_w3[n2] = 1;
    						k1         = n2;
    						k++;
    					}
    					else
    						sw1 = 1;
    				}
    				else
    					sw1 = 1;
    			}
    		}
    			//
    			// 近傍を固定
    			//
    		else {
    
    			n3  = (int)(rn.NextDouble() * (n_city - 2));
    			if (n3 > n_city-3)
    				n3 = n_city - 3;
                             // 2近傍
    			for (i1 = 0; i1 <= n_city-3 && ch == 0; i1++) {
    
    				if (n3 == 0)
    					n1 = n_city - 2;
    				else
    					n1 = n_city - 1;
    
    				for (i2 = n3+2; i2 <= n1 && ch == 0; i2++) {
                                  // 枝の場所((n3,n3+1), (k1,k2))
    					k1 = i2;
    					if (i2 == n_city-1)
    						k2 = 0;
    					else
    						k2 = i2 + 1;
                                  // 枝の入れ替え
    					seq_w1[0] = seq[n3];
    					k         = 1;
    					for (i3 = k1; i3 >= n3+1; i3--) {
    						seq_w1[k] = seq[i3];
    						k++;
    					}
    
    					nn = k2;
    					while (nn != n3) {
    						seq_w1[k] = seq[nn];
    						k++;
    						nn++;
    						if (nn > n_city-1)
    							nn = 0;
    					}
                                  // 評価
    					r = kyori(n_city, seq_w1, rg);
    
    					if (r < max) {
    						max = r;
    						sw  = 1;
    						for (i3 = 0; i3 < n_city; i3++)
    							seq_w2[i3] = seq_w1[i3];
    						if (sel > 0)
    							ch = 1;
    					}
    				}
    
    				n3++;
    				if (n3 > n_city-3)
    					n3 = 0;
    			}
                             // 3近傍
    			if (neib == 3 && ch == 0) {
    
    				for (i1 = 0; i1 <= n_city-3 && ch == 0; i1++) {
    
    					n1 = n_city - 2;
    					n2 = n_city - 1;
    
    					for (i2 = n3+1; i2 <= n1 && ch == 0; i2++) {
    
    						for (i3 = i2+1; i3 <= n2 && ch == 0; i3++) {
                                  // 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2))
    							k1 = i3;
    							if (i3 == n_city-1)
    								k2 = 0;
    							else
    								k2 = i3 + 1;
                                  // 枝の入れ替えと評価
                                       // 入れ替え(その1)
    							seq_w1[0] = seq[n3];
    							k         = 1;
    							for (i4 = i2; i4 >= n3+1; i4--) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							for (i4 = k1; i4 >= i2+1; i4--) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							nn = k2;
    							while (nn != n3) {
    								seq_w1[k] = seq[nn];
    								k++;
    								nn++;
    								if (nn > n_city-1)
    									nn = 0;
    							}
                                       // 評価(その1)
    							r = kyori(n_city, seq_w1, rg);
    
    							if (r < max) {
    								max = r;
    								sw  = 1;
    								for (i3 = 0; i3 < n_city; i3++)
    									seq_w2[i3] = seq_w1[i3];
    								if (sel > 0)
    									ch = 1;
    							}
                                       // 入れ替え(その2)
    							seq_w1[0] = seq[n3];
    							k         = 1;
    							for (i4 = k1; i4 >= i2+1; i4--) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							for (i4 = n3+1; i4 <= i2; i4++) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							nn = k2;
    							while (nn != n3) {
    								seq_w1[k] = seq[nn];
    								k++;
    								nn++;
    								if (nn > n_city-1)
    									nn = 0;
    							}
                                       // 評価(その2)
    							r = kyori(n_city, seq_w1, rg);
    
    							if (r < max) {
    								max = r;
    								sw  = 1;
    								for (i3 = 0; i3 < n_city; i3++)
    									seq_w2[i3] = seq_w1[i3];
    								if (sel > 0)
    									ch = 1;
    							}
                                       // 入れ替え(その3)
    							seq_w1[0] = seq[n3];
    							k         = 1;
    							for (i4 = i2+1; i4 <= k1; i4++) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							for (i4 = i2; i4 >= n3+1; i4--) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							nn = k2;
    							while (nn != n3) {
    								seq_w1[k] = seq[nn];
    								k++;
    								nn++;
    								if (nn > n_city-1)
    									nn = 0;
    							}
                                       // 評価(その3)
    							r = kyori(n_city, seq_w1, rg);
    
    							if (r < max) {
    								max = r;
    								sw  = 1;
    								for (i3 = 0; i3 < n_city; i3++)
    									seq_w2[i3] = seq_w1[i3];
    								if (sel > 0)
    									ch = 1;
    							}
                                       // 入れ替え(その4)
    							seq_w1[0] = seq[n3];
    							k         = 1;
    							for (i4 = i2+1; i4 <= k1; i4++) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							for (i4 = n3+1; i4 <= i2; i4++) {
    								seq_w1[k] = seq[i4];
    								k++;
    							}
    
    							nn = k2;
    							while (nn != n3) {
    								seq_w1[k] = seq[nn];
    								k++;
    								nn++;
    								if (nn > n_city-1)
    									nn = 0;
    							}
                                       // 評価(その4)
    							r = kyori(n_city, seq_w1, rg);
    
    							if (r < max) {
    								max = r;
    								sw  = 1;
    								for (i3 = 0; i3 < n_city; i3++)
    									seq_w2[i3] = seq_w1[i3];
    								if (sel > 0)
    									ch = 1;
    							}
    						}
    					}
    
    					n3++;
    					if (n3 > n_city-3)
    						n3 = 0;
    				}
    			}
    		}
                             // 設定
    		if (sw > 0) {
    			range = max;
    			for (i1 = 0; i1 < n_city; i1++)
    				seq[i1] = seq_w2[i1];
    		}
    
    		return sw;
    	}
    
    	/*********************************/
    	/* 距離の計算                    */
    	/*      n_c : 都市の数           */
    	/*      p : 都市番号             */
    	/*      rg : 都市間の距離        */
    	/*      return : 距離            */
    	/*********************************/
    	public static float kyori(int n_c, int [] p, float [][] rg)
    	{
    		float range = 0;
    		int n1 = p[0], n2;
    
    		for (int i1 = 1; i1 < n_c; i1++) {
    			n2     = p[i1];
    			range += rg[n1][n2];
    			n1     = n2;
    		}
    
    		n2     = p[0];
    		range += rg[n1][n2];
    
    		return range;
    	}
    }
    
    class Program
    {
    	static void Main(String[] args)
    	{
    						// 入力ミス
    		if (args.Length == 0)
    			Console.WriteLine("***error  ケーススタディファイル名を入力して下さい");
    						// 入力OK
    		else {
    							// 入力データファイル名と問題数
    			String[] lines = File.ReadAllLines(args[0]);
    			String[] str   = lines[0].Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
    			int nm         = int.Parse(str[1]);   // 問題の数
    
    			for (int i0 = 1; i0 <= nm; i0++) {
    								// 各問題の実行
    				str           = lines[i0].Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
    				String i_file = str[1];   // データファイル名
    				int n         = int.Parse(str[3]);   // 繰り返し回数
    
    				Partition pt = new Partition(i_file);
    				double mean  = 0.0;
    				int    max   = -1;
    									// 乱数の初期値を変える
    				for (int i1 = 0; i1 < n; i1++) {
    
    					Console.WriteLine();
    					Console.WriteLine("+++++問題 " + i_file + "+++++");
    									// 最適化
    					pt.Optimize(1000 * i1 + 1234567);   // 引数は乱数の初期値
    									// 最適値とその平均の計算
    					mean += pt.Max;
    					if (max < 0 || pt.Max < max)
    						max = pt.Max;
    				}
    				mean /= n;
    							// 結果
    				if (pt.out_m <= 0)
    					Console.WriteLine("     -----最小 " + max + " 平均 " + mean + "-----");
    				else {
    					StreamWriter OUT = new StreamWriter(pt.o_file, true);
    					OUT.WriteLine("     -----最小 " + max + " 平均 " + mean + "-----");
    					OUT.Close();
    				}
    			}
    		}
    	}
    }
    
    //------------------------ケーススタディデータ(data.txt)------
    /*
    問題の数 2
    問題 data1.txt 繰り返し回数 2
    問題 data2.txt 繰り返し回数 1
    */
    //---------------------データファイル(data1.txt)------------
    /*
    都市の数 50 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 2 Y 2 最大試行回数 1000
    86.950684 27.711487
    82.357788 16.148376
    29.791260 37.959290
    27.493286 1.542664
    90.893555 88.734436
    40.109253 92.308044
    87.445068 53.474426
    24.893188 99.382019
    11.633301 80.616760
    61.532593 8.702087
    30.645752 93.598938
    4.714966 81.205750
    86.669922 90.858459
    84.127808 52.830505
    96.893311 45.832825
    4.458618 34.513855
    53.503418 6.959534
    45.394897 12.193298
    23.687744 97.676086
    61.624146 46.806335
    49.633789 16.419983
    82.833862 74.290466
    48.529053 36.628723
    13.711548 5.583191
    12.561035 6.739807
    33.944702 26.622009
    8.917236 50.190735
    98.220825 98.344421
    79.785156 65.419006
    36.227417 56.687927
    42.352295 25.862122
    52.651978 12.590027
    88.806152 79.957581
    27.182007 51.988220
    86.334229 51.142883
    14.505005 35.820007
    77.124023 37.855530
    44.308472 0.022888
    78.363037 13.533020
    21.279907 55.534363
    82.238770 26.612854
    25.106812 88.291931
    55.938721 0.532532
    10.476685 59.233093
    41.650391 33.729553
    7.077026 4.295349
    56.561279 99.641418
    19.595337 34.416199
    92.858887 46.705627
    27.719116 35.533142
    */
    
    //---------------------データファイル(data2.txt)------------
    /*
    都市の数 10 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 1 Y 1 最大試行回数 1000
    8.695068 2.771149
    8.235779 1.614838
    2.979126 3.795929
    2.749329 0.154266
    9.089355 8.873444
    4.010925 9.230804
    8.744507 5.347443
    2.489319 9.938202
    1.163330 8.061676
    6.153259 0.870209
    */
    			

  7. VB

    '**************************'
    ' 巡回セールスマン問題     '
    ' (分割法)               '
    '      coded by Y.Suganuma '
    '**************************'
    Imports System.IO
    Imports System.Text.RegularExpressions
    
    Module Test
    
    	Sub Main(args() As String)
    						' 入力ミス
    		If args.Length = 0
    			Console.WriteLine("***error  ケーススタディファイル名を入力して下さい")
    						' 入力OK
    		Else
    			Dim MS As Regex = New Regex("\s+") 
    							' 入力データファイル名と問題数
    			Dim inp As StreamReader = New StreamReader(args(0))
    			Dim str() As String     = MS.Split(inp.ReadLine().Trim())
    			Dim nm As Integer       = Integer.Parse(str(1))   ' 問題の数
    
    			For i0 As Integer = 1 To nm
    								' 各問題の実行
    				str = MS.Split(inp.ReadLine().Trim())
    				Dim i_file As String = str(1)   ' データファイル名
    				Dim n As Integer     = Integer.Parse(str(3))   ' 繰り返し回数
    
    				Dim pt As Partition  = new Partition(i_file)
    				Dim mean As Double   = 0.0
    				Dim max As Integer   = -1
    									' 乱数の初期値を変える
    				For i1 As Integer = 0 To n-1
    
    					Console.WriteLine()
    					Console.WriteLine("+++++問題 " & i_file & "+++++")
    									' 最適化
    					pt.Optimize(1000 * i1 + 1234567)   ' 引数は乱数の初期値
    									' 最適値とその平均の計算
    					mean += pt.Max
    					If max < 0 or pt.Max < max
    						max = pt.Max
    					End If
    				Next
    				mean /= n
    							' 結果
    				If pt.out_m <= 0
    					Console.WriteLine("     -----最小 " & max & " 平均 " & mean & "-----")
    				Else
    					Dim Out As StreamWriter = New StreamWriter(pt.o_file, true)
    					OUT.WriteLine("     -----最小 " & max & " 平均 " & mean & "-----")
    					OUT.Close()
    				End If
    			Next
    			inp.Close()
    		End If
    
    	End Sub
    
    	'*******************************'
    	' 距離の計算                    '
    	'      n_c : 都市の数           '
    	'      p : 都市番号             '
    	'      rg : 都市間の距離        '
    	'      return : 距離            '
    	'*******************************'
    	Function kyori(n_c As Integer, p() As Integer, rg(,) As Double)
    
    		Dim range As Double = 0
    		Dim n1 As Integer   = p(0)
    		Dim n2 As Integer
    	
    		For i1 As Integer = 1 To n_c-1
    			n2     = p(i1)
    			range += rg(n1,n2)
    			n1     = n2
    		Next
    	
    		n2     = p(0)
    		range += rg(n1,n2)
    	
    		Return range
    
    	End Function
    	
    	'***********************'
    	' クラスPartitionの定義 '
    	'***********************'
    	Class Partition
    
    		Private rg(,) As Double   ' 都市間の距離
    		Private p_x() As Double   ' x軸の分割点
    		Private p_y()  As Double  ' y軸の分割点
    		Private fix As Integer   ' =1 : 近傍を固定
    	                             ' =0 : 近傍を可変
    		Private max_try As Integer   ' 最大試行回数
    		Private seq_w1() As Integer   ' 作業領域
    		Private seq_w2() As Integer   ' 作業領域
    		Private neib As Integer   ' 近傍(2 or 3)
    		Public seisu As Integer   ' 位置データの表現方法
    	                              '   =1 : 整数
    	                              '   =-1 : 実数(距離を整数計算)
    	                              '   =-2 : 実数(距離を実数計算)
    		Private sel As Integer   ' エッジの選択方法
    	                             '   =0 : 最良のものを選択
    	                             '   =1 : 最初のものを選択
    		Private rn As Random   ' 乱数
    	
    		Private city(,) As Double   '都市の位置データ
    		Private city_i(,) As Double   '都市の位置データ(作業領域)
    		Public Max As Integer   ' 最適経路の長さ
    		Private n_city As Integer   ' 都市の数
    		Private n_seq(,) As Integer   ' 各領域の都市数
    		Private n_seq1(,) As Integer   ' 各領域の都市数(ワーク)
    		Private n_p_x As Integer   ' x軸方向の分割数
    		Private n_p_y As Integer   ' y軸方向の分割数
    		Public out_m As Integer   ' 出力方法
     	                              '   =-1 : ディスプレイ(経路長だけ)
    	                              '   =0 : ディスプレイ
    	                              '   =1 : ファイル
    	                              '   =2 : ファイル(経路長だけ)
    		Private range As Integer   ' 現在の評価値
    		Private seed As Integer   ' 乱数の初期値
    		Private seq(,,) As Integer   ' 経路
    		Private seq1(,,) As Integer   ' 経路(ワーク)
    		Private state(,) As Integer   ' 領域結合用ワーク
    		Public o_file As String    ' 出力ファイル名
    		Private i_file As String   ' 入力ファイル名
    	
    		'**************************'
    		' コンストラクタ           '
    		'      i_file : ファイル名 '
    		'**************************'
    		Public Sub New (name As String)
    
    			i_file = name
    			Dim MS As Regex         = New Regex("\s+") 
    			Dim inp As StreamReader = New StreamReader(i_file)
    						' 基本データ
    							' 1行目
    			Dim str() As String = MS.Split(inp.ReadLine().Trim())
    			n_city              = Integer.Parse(str(1))
    			sel                 = Integer.Parse(str(3))
    			neib                = Integer.Parse(str(5))
    			seisu               = Integer.Parse(str(7))
    			If neib < 0
    				neib = -neib
    				fix  = 0
    			Else
    				fix = 1
    			End If
    							' 2行目
    			str    = MS.Split(inp.ReadLine().Trim())
    			out_m  = Integer.Parse(str(1))
    			o_file = str(3)
    							' 3行目
    			str     = MS.Split(inp.ReadLine().Trim())
    			n_p_x   = Integer.Parse(str(2))
    			n_p_y   = Integer.Parse(str(4))
    			max_try = Integer.Parse(str(6))
    						' 都市の位置データ
    			ReDim city(n_city, 2)
    			For i1 As Integer = 0 To n_city-1
    				str        = MS.Split(inp.ReadLine().Trim())
    				city(i1,0) = Double.Parse(str(0))
    				city(i1,1) = Double.Parse(str(1))
    			Next
    			inp.Close()
    						' 距離テーブルの作成
    			ReDim rg(n_city, n_city)
    	
    			For i1 As Integer = 0 To n_city-1
    				For i2 As Integer = i1+1 To n_city-1
    					Dim x As Double = city(i2,0) - city(i1,0)
    					Dim y As Double = city(i2,1) - city(i1,1)
    					rg(i1,i2)       = Math.Sqrt(x * x + y * y)
    					If seisu > -2
     						rg(i1,i2) = Math.Floor(rg(i1,i2) + 0.5)
    					End If
    				Next
    			Next
    	
    			For i1 As Integer = 1 To n_city-1
    				For i2 As Integer = 0 To i1-1
    					rg(i1,i2) = rg(i2,i1)
    				Next
    			Next
    						' 作業領域
    			ReDim state(n_p_y, n_p_x)
    			ReDim n_seq(n_p_y, n_p_x)
    			ReDim n_seq1(n_p_y, n_p_x)
    	
    			ReDim seq(n_p_y, n_p_x, n_city)
    			ReDim seq1(n_p_y, n_p_x, n_city)
    	
    			ReDim seq_w1(n_city)
    			ReDim seq_w2(n_city)
    			ReDim p_x(n_p_x)
    			ReDim p_y(n_p_y)
    						' 都市の分割
    			For i1 As Integer = 0 To n_city-1
    				seq_w1(i1) = 0
    			Next
    
    			Dim min_x As Double = city(0,0)
    			Dim max_x As Double = city(0,0)
    			Dim min_y As Double = city(0,1)
    			Dim max_y As Double = city(0,1)
    	
    			For i1 As Integer = 1 To n_city-1
    				If city(i1,0) < min_x
    					min_x = city(i1,0)
    				Else
    					If city(i1,0) > max_x
    						max_x = city(i1,0)
    					End If
    				End If
    				If city(i1,1) < min_y
    					min_y = city(i1,1)
    				Else
    					If city(i1,1) > max_y
    						max_y = city(i1,1)
    					End If
    				End If
    			Next
    	
    			Dim s_x As Double = (max_x - min_x) / n_p_x
    			p_x(0)            = min_x + s_x
    			p_x(n_p_x-1)      = max_x
     			For i1 As Integer = 1 To n_p_x-2
    				p_x(i1) = p_x(0) + i1 * s_x
    			Next
    
    			Dim s_y As Double = (max_y - min_y) / n_p_y
    			p_y(0)            = min_y + s_y
    			p_y(n_p_y-1)      = max_y
    			For i1 As Integer = 1 To n_p_y-2
    				p_y(i1) = p_y(0) + i1 * s_y
    			Next
    
    			Dim max As Integer = 0
    			For i1 As Integer = 0 To n_p_y-1
    				For i2 As Integer = 0 To n_p_x-1
    					Dim n As Integer = 0
    					For i3 As Integer = 0 To n_city-1
    						If seq_w1(i3) = 0
    							If city(i3,0) <= p_x(i2) and city(i3,1) <= p_y(i1)
    								seq_w1(i3) = 1
    								seq_w2(n)  = i3
    								n += 1
    							End If
    						End If
    					Next
    					n_seq1(i1,i2) = n
    					If n > 0
    						For i3 As Integer = 0 To n-1
    							seq1(i1,i2,i3) = seq_w2(i3)
    						Next
    						If n > max
    							max = n
    						End If
    					End If
    				Next
    			Next
    	
    			For i1 As Integer = 0 To n_p_y-1
    				For i2 As Integer = 0 To n_p_x-1
    					state(i1,i2) = 1
    					If n_seq1(i1,i2) > 0
    						state(i1,i2) = 0
    					End If
    				Next
    			Next
    						' 作業領域
    			Console.WriteLine("最大都市数 " & max)
    			ReDim city_i(max, 2)
    
    		End Sub
    	
    		'****************************'
    		' 最適化の実行               '
    		'      seed_i : 乱数の初期値 '
    		'****************************'
    		Public Sub Optimize(seed_i As Integer)
    
    						' 乱数の初期設定
    			seed = seed_i
    			rn   = new Random(seed)   ' rn.NextDouble()
    	
    			For i1 As Integer = 0 To n_p_y-1
    				For i2 As Integer = 0 To n_p_x-1
    					n_seq(i1,i2) = n_seq1(i1,i2)
    					state(i1,i2) = 1
    					If n_seq1(i1,i2) > 0
    						state(i1,i2) = 0
    					End If
    					For i3 As Integer = 0 To n_seq1(i1,i2)-1
    						seq(i1,i2,i3) = seq1(i1,i2,i3)
    					Next
    				Next
     			Next
    							' 分割数と開始時間の出力(ファイルへ出力する場合)
    			If out_m > 0
    				Output(0)
    			End If
    							' 分割毎の最適化
    			For i1 As Integer = 0 To n_p_y-1
    				For i2 As Integer = 0 To n_p_x-1
    					If n_seq(i1,i2) > 3
    								' 近傍の大きさ
    						Dim nb As Integer
    						if n_seq(i1,i2) > 3
    							nb = neib
    						Else
    							nb = 2
    						End If
    								' 都市位置データの設定
    						For i3 As Integer = 0 To n_seq(i1,i2)-1
    							Dim k As Integer = seq(i1,i2,i3)
    							city_i(i3,0)     = city(k,0)
    							city_i(i3,1)     = city(k,1)
    						Next
    								' 最適化
    						Dim it As Iteration = new Iteration (n_seq(i1,i2), max_try,
    						                      seisu, sel, nb, fix, 0, -1, 0, o_file,
    						                      city_i, rn)
    						Dim max As Integer  = it.Optimize()
    								' 結果の保存
    						For i3 As Integer = 0 To n_seq(i1,i2)-1
    							Dim k As Integer = it.seq(i3)
    							seq_w1(i3)       = seq(i1,i2,k)
    						Next
    						For i3 As Integer = 0 To n_seq(i1,i2)-1
    							seq(i1,i2,i3) = seq_w1(i3)
    						Next
    								' 出力(文字)
    						Dim r As Integer
    						Dim sq(n_seq(i1,i2)) As Integer
    						For i3 As Integer = 0 TO n_seq(i1,i2)-1
    							sq(i3) = seq(i1,i2,i3)
    						Next
    						If seisu > -2
    							r = Math.Floor(kyori(n_seq(i1,i2), sq, rg))
    						Else
    							r = Math.Floor(kyori(n_seq(i1,i2), sq, rg) + 0.5)
    						End If
    						Console.WriteLine("   y " & (i1+1) & " x " & (i2+1) &
    	                                     " n_city " & n_seq(i1,i2) &
    	                                     " range " & r & " (trial " & max & ")")
    					End If
    				Next
    			Next
    							' 経路の接続
    			range = Connect()
    			Max   = range
    							' 出力(文字)
    			Output(n_city)
    
    		End Sub
    
    		'*********************'
    		' 出力                '
    		'      n_c : 都市の数 '
    		'*********************'
    		Sub Output(n_c As Integer)
    
    			Dim OUT As StreamWriter = new StreamWriter(o_file, true)
    			If out_m <= 0
    				Console.WriteLine("距離 " & range)
    				Console.ReadLine()
    			Else
    				Dim now1 As DateTime = DateTime.Now   ' 現在時刻の獲得
    				If n_c > 0
    					Console.WriteLine("距離 " & range)
     					OUT.WriteLine("   距離 " & range & " 時間 " & now1)
    				Else
    					OUT.WriteLine("問題 " & i_file & " 乱数 " & seed & " 分割 " & n_p_x &
    					              " " & n_p_y & " 時間 " & now1)
    				End If
    			End If
    	
    			Dim k As Integer = 0
    			If n_c > 0 and (out_m = 0 or out_m = 1)
    				For i1 As Integer = 0 To n_c-1
    					Dim n As Integer = seq_w1(i1)
    					If out_m > 0
    						If seisu > 0
    							OUT.WriteLine("  " & n & " " & Math.Floor(city(n,0)) & " " & Math.Floor(city(n,1)))
    						Else
    							OUT.WriteLine("  " & n & " " & city(n,0) & " " & city(n,1))
    						End If
    					Else
    						If seisu > 0
    							Console.WriteLine("  " & n & " " & Math.Floor(city(n,0)) & " " & Math.Floor(city(n,1)))
    						Else
    							Console.WriteLine("  " & n & " " & city(n,0) & " " & city(n,1))
    						End If
    					End If
    					If out_m = 0
    						k += 1
    						If k = 10
    							Console.ReadLine()
    							k = 0
    						End If
    					End If
    				Next
    			End If
    	
    			OUT.Close()
    
    		End Sub
    
    		'**********************'
    		' 分割された領域の接続 '
    		'**********************'
    		Function Connect()
    
    			Dim wd As Double
    			Dim wd1 As Double
    			Dim wa1 As Double
    			Dim wa2 As Double
    			Dim min As Double = 0
    			Dim i1 As Integer
    			Dim i2 As Integer
    			Dim i3 As Integer
    			Dim i4 As Integer
    			Dim k As Integer
    			Dim k1 As Integer = 0
    			Dim k2 As Integer = 0
    			Dim k3 As Integer = 0
    			Dim k4 As Integer = 0
    			Dim min_c As Integer = 0
    			Dim n As Integer
    			Dim r As Integer
    			Dim r1 As Integer = 0
    			Dim r2 As Integer = 0
    			Dim r3 As Integer = 0
    			Dim r4 As Integer = 0
    			Dim s1 As Integer = 0
    			Dim s2 As Integer = 0
    			Dim sw As Integer = 1
    					'
    					' 領域が1つの場合
    					'
    			If n_p_x = 1 and n_p_y = 1
    				For i1 = 0 To n_seq(0,0)-1
    					seq_w1(i1) = seq(0,0,i1)
    				Next
    					'
    					' 領域が複数の場合
    					'
    			Else
    	
    				Do While sw > 0
    							' 最小節点領域
    					min_c = n_city
    					sw    = 0
     					For i1 = 0 To n_p_y-1
    						For i2 = 0 To n_p_x-1
    							If state(i1,i2) = 0 and n_seq(i1,i2) < min_c
    								sw    = 1
    								r1    = i1
    								r2    = i2
    								min_c = n_seq(i1,i2)
    							End If
    						Next
    					Next
    							' 結合する対象領域の決定
    					If sw > 0
    						sw = 0
    						For i1 = 0 To n_p_y-1
    							For i2 = 0 To n_p_x-1
    								If state(i1,i2) = 0 and (i1 <> r1 or i2 <> r2)
    										' 節点の数>2
    									If n_seq(r1,r2) > 1
    										For i3 = 0 To n_seq(r1,r2)-1
    											k1  = seq(r1,r2,i3)
    											if i3 = n_seq(r1,r2)-1
    												k2 = seq(r1,r2,0)
    											Else
    												k2 = seq(r1,r2,i3+1)
    											End If
    											wd1 = rg(k1,k2)
    											For i4 = 0 To n_seq(i1,i2)-1
    												k3  = seq(i1,i2,i4)
    												If i4 = n_seq(i1,i2)-1
    													k4 = seq(i1,i2,0)
    												Else
    													k4 = seq(i1,i2,i4+1)
    												End If
    												wd  = wd1 + rg(k3,k4)
    												wa1 = rg(k1,k3) + rg(k2,k4)
    												wa2 = rg(k1,k4) + rg(k2,k3)
    												If sw = 0 or wa1-wd < min
    													min = wa1 - wd
    													r3  = i1
    													r4  = i2
    													If i3 = n_seq(r1,r2)-1
    														s1 = 0
    													Else
    														s1 = i3 + 1
    													End If
    													If i4 = n_seq(i1,i2)-1
    														s2 = 0
    													Else
    														s2 = i4 + 1
    													End If
    													sw = -1
    												End If
    												If sw = 0 or wa2-wd < min
    													min = wa2 - wd
    													r3  = i1
    													r4  = i2
    													s1  = i3
    													s2  = 0
    													If i4 = n_seq(i1,i2)-1
    														s2  = 0
    													Else
    														s2 = i4 + 1
    													End If
    													sw = 1
    												End If
    											Next
    										Next
    										' 節点の数=1
    									Else
    										k1 = seq(r1,r2,0)
    										If n_seq(i1,i2) > 1
    											For i4 = 0 To n_seq(i1,i2)-1
    												k3  = seq(i1,i2,i4)
    												If i4 = n_seq(i1,i2)-1
    													k4 = seq(i1,i2,0)
    												Else
    													k4 = seq(i1,i2,i4+1)
    												End If
    												wd  = rg(k3,k4)
    												wa1 = rg(k1,k3) + rg(k1,k4)
    												If sw = 0 or wa1-wd < min
     													min = wa1 - wd
    													r3  = i1
    													r4  = i2
    													s1  = 0
    													If i4 = n_seq(i1,i2)-1
    														s2 = 0
    													Else
    														s2 = i4 + 1
    													End If
    													sw  = 1
    												End If
    											Next
    										Else
    											k3  = seq(i1,i2,0)
    											wa1 = rg(k1,k3)
    											If sw = 0 or wa1 < min
    												min = wa1
    												r3  = i1
    												r4  = i2
    												s1  = 0
    												s2  = 0
    												sw  = 1
    											End If
    										End If
    									End If
    								End If
    							Next
    						Next
    							' 領域の結合
    						seq_w1(0) = seq(r1,r2,s1)
    						k         = 1
    						n         = s2
    						For i1 = 0 To n_seq(r3,r4)-1
    							seq_w1(k) = seq(r3,r4,n)
    							k        += 1
    							n        += 1
    							If n > n_seq(r3,r4)-1
    								n = 0
    							End If
    						Next
    						If sw > 0
    							n = s1 + 1
    							For i1 = 0 To n_seq(r1,r2)-2
    								If n > n_seq(r1,r2)-1
    									n = 0
    								End If
    								seq_w1(k) = seq(r1,r2,n)
    								k        += 1
    								n        += 1
    							Next
    						Else
    							n = s1 - 1
    							For i1 = 0 To n_seq(r1,r2)-2
    								If n < 0
    									n = n_seq(r1,r2) - 1
    								End If
    								seq_w1(k) = seq(r1,r2,n)
    								k        += 1
    								n        -= 1
    							Next
    						End If
    							' 状態の変更
    						n_seq(r1,r2) += n_seq(r3,r4)
    						state(r3,r4)  = 1
    						For i1 = 0 To n_seq(r1,r2)-1
     							seq(r1,r2,i1) = seq_w1(i1)
    						Next
    						sw  = 1
    					End If
    				Loop
    			End If
    	
    			If seisu > -2
    				r = Math.Floor(kyori(n_city, seq_w1, rg))
    			Else
    				r = Math.Floor(kyori(n_city, seq_w1, rg) + 0.5)
    			End If
    	
    			Return r
    
    		End Function
    
    	End Class
    	
    	'***********************'
    	' クラスIterationの定義 '
    	'***********************'
    	Class Iteration
    
    		Private rg(,) As Double   ' 都市間の距離
    		Private fix As Integer   ' =1 : 近傍を固定
    	                             ' =0 : 近傍を可変
    		Private max_try As Integer   ' 最大試行回数
    		Private neib As Integer   ' 近傍(2 or 3)
    		Private out_d As Integer   ' 表示間隔
    		Private seq_w1() As Integer   ' 都市を訪れる順序(ワーク)
    		Private seq_w2() As Integer   ' 都市を訪れる順序(ワーク)
    		Private seq_w3() As Integer   ' 都市を訪れる順序(ワーク)
    		Private seq_w4() As Integer   ' 都市を訪れる順序(ワーク)
    		Private seq_w5() As Integer   ' 都市を訪れる順序(ワーク)
    		Private out_lvl As Integer   ' 出力レベル
    	                                 '   =0 : 最終出力だけ
    	                                 '   n>0 : n世代毎に出力(負の時はファイル)
    		Private out_m As Integer   ' 出力方法
    	                               '   =-1 : 出力しない
    	                               '   =0 : すべてを出力
    	                               '   =1 : 評価値だけを出力(最終結果だけはすべてを出力)
    		Private seisu As Integer   ' 位置データの表現方法
    	                               '   =1 : 整数
    	                               '   =-1 : 実数(距離を整数計算)
    	                               '   =-2 : 実数(距離を実数計算)
    		Private sel As Integer   ' エッジの選択方法
    	                             '   =0 : 最良のものを選択
    	                             '   =1 : 最初のものを選択
    		Private o_file As String   ' 出力ファイル名
    		Private rn As Random   ' 乱数
    	
    		Private range As Double   ' 現在の評価値
    		Private city(,) As Double  '都市の位置データ
    		Private n_city As Integer   ' 都市の数
    		Private n_tri As Integer   ' 試行回数
    		Public seq() As Integer   ' 都市を訪れる順序
    	
    		'********************************'
    		' コンストラクタ                 '
    		'      n_city_i : 都市の数       '
    		'      max_try_i : 最大試行回数  '
    		'      sei_i : 整数 or 実数      '
    		'      sel_i : エッジの選択方法  '
    		'      neib_i : 近傍(2 or 3)   '
    		'      fix_i : 近傍の扱い方      '
    		'      out_lvl_i : 出力レベル    '
     		'      out_m_i : 出力方法        '
    		'      out_d_i : 表示間隔        '
    		'      o_file_i : 出力ファイル名 '
    		'      city_i : 都市の位置データ '
    		'      rn_i : 乱数               '
    		'********************************'
    		Public Sub New (n_city_i As Integer, max_tri_i As Integer, sei_i As Integer,
    		                sel_i As Integer, neib_i As Integer, fix_i As Integer,
    	 	                out_lvl_i As Integer, out_m_i As Integer, out_d_i As Integer,
    						o_file_i As String, city_i(,) As Double, rn_i As Random)
    
    							' 値の設定
    			n_city  = n_city_i
    			max_try = max_tri_i
    			seisu   = sei_i
    			sel     = sel_i
    			neib    = neib_i
    			fix     = fix_i
    			out_lvl = out_lvl_i
    			out_m   = out_m_i
    			out_d   = out_d_i
    			o_file  = o_file_i
    			rn      = rn_i
    			n_tri   = 0
    							' 都市の位置データ
    			ReDim city(n_city, 2)
    			For i1 As Integer = 0 To n_city-1
    				city(i1,0) = city_i(i1,0)
    				city(i1,1) = city_i(i1,1)
    			Next
    							' 距離テーブルの作成
    			ReDim rg(n_city, n_city)
    	
    			For i1 As Integer = 0 To n_city-1
    				For i2 As Integer = i1+1 To n_city-1
    					Dim x As Double   = city(i2,0) - city(i1,0)
    					Dim y As Double   = city(i2,1) - city(i1,1)
    					rg(i1,i2) = Math.Sqrt(x * x + y * y)
    					If seisu > -2
    						rg(i1,i2) = Math.Floor(rg(i1,i2) + 0.5)
    					End If
    				Next
    			Next
    	
    			For i1 As Integer = 1 To n_city-1
    				For i2 As Integer = 0 To i1-1
    					rg(i1,i2) = rg(i2,i1)
    				Next
    			Next
    							' 都市を訪れる順序(初期設定)
    			ReDim seq(n_city)
    			ReDim seq_w1(n_city)
    			ReDim seq_w2(n_city)
    			ReDim seq_w3(n_city)
    			ReDim seq_w4(n_city)
    			ReDim seq_w5(n_city)
    	
    			For i1 As Integer = 0 To n_city-1
    				Dim sw As Integer = 0
    				Do While sw = 0
    					Dim ct As Integer = Math.Floor(rn.NextDouble() * n_city)
     					If ct >= n_city
    						ct = n_city - 1
    					End If
    					seq(i1) = ct
    					sw      = 1
    					Dim ii As Integer = 0
    					Do While ii < i1 and sw > 0
    						If ct = seq(ii)
    							sw = 0
    						End If
    						ii += 1
    					Loop
    				Loop
    			Next
    
    		End Sub
    
    		'**************'
    		' 最適化の実行 '
    		'**************'
    		Public Function Optimize ()
    
    			Dim sw As Integer
    					' 初期設定
    			range = kyori(n_city, seq, rg)
    					' 初期状態の出力(文字)
    			If out_m >= 0 and Math.Abs(out_lvl) > 0
    				If seisu > -2
    					Console.WriteLine("***試行回数 " & n_tri & " 距離 " & Math.Floor(range))
    				Else
    					Console.WriteLine("***試行回数 " & n_tri & " 距離 " & range)
    				End If
    				Output(out_lvl)
    			End If
    					' 実行
    			sw    = 1
    			n_tri = 1
    			Do While n_tri <= max_try and sw > 0
    						' 改善
    				sw = Change()
    								' 出力(文字)
    				If out_d > 0
    					If (n_tri Mod out_d) = 0
    						If seisu > -2
    							Console.WriteLine("***試行回数 " & n_tri & " 距離 " & Math.Floor(range))
    						Else
    							Console.WriteLine("***試行回数 " & n_tri & " 距離 " & range)
    						End If
    					End If
    				End If
    	
    				If out_m >= 0 and Math.Abs(out_lvl) > 0
    					If (n_tri Mod Math.Abs(out_lvl)) = 0
    						Output(out_lvl)
    					End If
    				End If
    			Loop
    					' 最終出力(文字)
    			If out_m >= 0
    				n_tri -= 1
    				If seisu > -2
    					Console.WriteLine("***試行回数 " & n_tri & " 距離 " + Math.Floor(range))
    				Else
    					Console.WriteLine("***試行回数 " & n_tri & " 距離 " + Math.Floor(range+0.5))
    				End If
    				Output(out_lvl)
    			End If
    	
    			Return n_tri
    
    		End Function
    
    		'*****************************'
     		' 出力                        '
    		'      sw : >= 0 : 出力先未定 '
    		'           < 0 : ファイル    '
    		'*****************************'
    		Sub Output(sw As Integer)
    
    			Dim pr As Integer = -1
    			If sw >= 0
    				Console.Write("   出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ")
    				pr = Integer.Parse(Console.ReadLine())
    			End If
    	
    			If pr <> 0
    	
    				Dim Out As StreamWriter = new StreamWriter(o_file, true)
    	
    				If pr < 0
    					Dim now1 As DateTime = DateTime.Now   ' 現在時刻の獲得
    					If seisu > -2
    						OUT.WriteLine("***試行回数 " & n_tri & " 距離 " & Math.Floor(range) & " 時間 " & now1)
    					Else
    						OUT.WriteLine("***試行回数 " & n_tri & " 距離 " & Math.Floor(range+0.5) & " 時間 " & now1)
    					End If
    				End If
    	
    				If out_m = 0
    					Dim k As Integer = 0
    					For i1 As Integer = 0 To n_city-1
    						Dim n As Integer = seq(i1)
    						If pr < 0
    							If seisu > 0
    								OUT.WriteLine("  " & n & " " & Math.floor(city(n,0)) & " " & Math.floor(city(n,1)))
    							Else
    								OUT.WriteLine("  " & n & " " & city(n,0) & " " & city(n,1))
    							End If
    						Else
    							If seisu > 0
    								Console.WriteLine("  " & n & " " & Math.floor(city(n,0)) & " " & Math.floor(city(n,1)))
    							Else
    								Console.WriteLine("  " & n & " " & city(n,0) & " " & city(n,1))
    							End If
    						End If
    						If pr > 0
    							k += 1
    							If k = pr
    								Console.ReadLine()
    								k = 0
    							End If
    						End If
    					Next
    				End If
    	
    				OUT.Close()
    
    			End If
    
    		End Sub
    
    		'************************************'
    		' エッジの入れ替え                   '
    		'      return : =0 : 改善がなかった  '
    		'               =1 : 改善があった    '
    		'************************************'
     		Function Change()
    
    			Dim max As Double  = range
    			Dim max1 As Double = 0.0
    			Dim r As Double
    			Dim ch As Integer = 0
    			Dim i0 As Integer
    			Dim i1 As Integer
    			Dim i2 As Integer
    			Dim i3 As Integer
    			Dim i4 As Integer
    			Dim k As Integer
    			Dim k1 As Integer = 0
    			Dim k2 As Integer = 0
    			Dim k3 As Integer
    			Dim k4 As Integer
    			Dim n As Integer
    			Dim nn As Integer
    			Dim n1 As Integer = 0
    			Dim n2 As Integer = 0
    			Dim n3 As Integer
    			Dim n4 As Integer
    			Dim sw As Integer  = 0
    			Dim sw1 As Integer = 0
    			Dim sw2
    				'
    				' 近傍を可変
    				'
    			If fix = 0
    						' 初期設定(k=2)
    				k = 2
    				For i1 = 0 To n_city-1
    					seq_w4(i1) = seq(i1)
    					seq_w3(i1) = 0
    				Next
    							' 評価
    				sw2 = 0
    				i0  = 0 
    				Do While i0 < n_city-2 and sw2 < 2
    	
    					If i0 = 0
    						n = n_city - 1
    					Else
    						n = n_city
    					End If
    	
    					i1 = i0 + 2
    					Do While i1 < n and sw2 < 2
    								' 相手の場所
    						k3 = i1
    						k4 = k3 + 1
    						If k4 > n_city-1
    							k4 = 0
    						End If
    								' 順番の入れ替え
    						n3 = -1
    						i2 = 0
    						Do While i2 < n_city and n3 < 0
    							If seq_w4(i2) = seq(i0+1)
    								n3 = i2 + 1
    							End If
    							i2 += 1
    						Loop
    						nn = n3
    						n4 = -1
    						i2 = 0
    						Do While i2 < n_city and n4 < 0
    							If nn > n_city-1
    								nn = 0
    							End If
    							If seq_w4(nn) = seq(k3) or seq_w4(nn) = seq(k4)
    								n4 = seq_w4(nn)
    							Else
    								nn += 1
    							End If
    							i2 += 1
    						Loop
    						If n4 = seq(k4)
    							n4 = k3
    							k3 = k4
    							k4 = n4
    						End If
    								' 評価
    						seq_w1(0) = seq(k4)
    						seq_w1(1) = seq(i0+1)
    						n4        = -1
    						nn        = 2
    						Do While n4 < 0
    							If n3 > n_city-1
    								n3 = 0
    							End If
    							seq_w1(nn) = seq_w4(n3)
    							If seq_w4(n3) = seq(k3)
     								n4 = 1
    							End If
    							nn += 1
    							n3 += 1
    						Loop
    						seq_w1(nn) = seq(i0)
    						nn += 1
    						n3  = -1
    						n4  = -1
    						i2  = 0
    						Do While i2 < n_city and n3 < 0
    							If seq_w4(i2) = seq(i0)
    								n3 = i2 - 1
    								If n3 < 0
    									n3 = n_city - 1
    								End If
    							End If
    							i2 += 1
    						Loop
    						Do While n4 < 0
    							If seq_w4(n3) = seq(k4)
    								n4 = 1
    							Else
    								seq_w1(nn) = seq_w4(n3)
    								nn += 1
    								n3 -= 1
    								If n3 < 0
    									n3 = n_city - 1
    								End If
    							End If
    						Loop
    	
    						r = kyori(n_city, seq_w1, rg)
    								' 最適値の保存
    						If sw2 = 0 or r < max1
    							sw2  = 1
    							max1 = r
    							n1   = k3
    							n2   = k4
    							k1   = i0
    							k2   = i0 + 1
    							For i2 = 0 To n_city-1
    								seq_w5(i2) = seq_w1(i2)
    							Next
    							If sel > 0 and max1 < max
    								sw2 = 2
    							End If
    						End If
    						i1 += 1
    					Loop
    					i0 += 1
    				Loop
    							' 最適値の保存と近傍の増加
    				If sw2 > 0
    					If max1 < max
    						sw  = 1
    						max = max1
    						For i1 = 0 To n_city-1
    							seq_w2(i1) = seq_w5(i1)
    						Next
    					End If
    					If k < neib
    						For i1 = 0 To n_city-1
    							seq_w4(i1) = seq_w5(i1)
    						Next
    						seq_w3(k1) = 1
    						seq_w3(k2) = 1
    						seq_w3(n1) = 1
    						seq_w3(n2) = 1
    						k1         = n2
    						k         += 1
     					Else
    						sw1 = 1
    					End If
    				Else
    					sw1 = 1
    				End If
    						' 実行(k>2)
    				Do While sw1 = 0
    							' 評価
    					sw2 = 0
    					For i1 = 0 To n_city-1
    								' 相手の場所
    						k3 = i1
    						k4 = k3 + 1
    						If k4 > n_city-1
    							k4 = 0
    						End If
    	
    						If seq_w3(k3) = 0 and seq_w3(k4) = 0
    								' 順番の入れ替え
    							n3 = -1
    							i2 = 0
    							Do While i2 < n_city and n3 < 0
    								If (seq_w4(i2) = seq(k2))
    									n3 = i2 + 1
    								End If
    								i2 += 1
    							Loop
    							nn = n3
    							n4 = -1
    							i2 = 0
    							Do While i2 < n_city and n4 < 0
    								If nn > n_city-1
    									nn = 0
    								End If
    								If seq_w4(nn) = seq(k3) or seq_w4(nn) = seq(k4)
    									n4 = seq_w4(nn)
    								Else
    									nn += 1
    								End If
    								i2 += 1
    							Loop
    							If n4 = seq(k4)
    								n4 = k3
    								k3 = k4
    								k4 = n4
    							End If
    								' 評価
    							seq_w1(0) = seq(k4)
    							seq_w1(1) = seq(k2)
    							n4        = -1
    							nn        = 2
    							Do While n4 < 0
    								If n3 > n_city-1
    									n3 = 0
    								End If
    								seq_w1(nn) = seq_w4(n3)
    								If seq_w4(n3) = seq(k3)
    									n4 = 1
    								End If
    								nn += 1
    								n3 += 1
    							Loop
    							seq_w1(nn) = seq(k1)
    							nn += 1
    							n3  = -1
    							n4  = -1
    							i2  = 0
    							Do While i2 < n_city and n3 < 0
    								If seq_w4(i2) = seq(k1)
    									n3 = i2 - 1
     									If n3 < 0
    										n3 = n_city - 1
    									End If
    								End If
    								i2 += 1
    							Loop
    							Do While n4 < 0
    								If seq_w4(n3) = seq(k4)
    									n4 = 1
    								Else
    									seq_w1(nn) = seq_w4(n3)
    									nn += 1
    									n3 -= 1
    									If n3 < 0
    										n3 = n_city - 1
    									End If
    								End If
    							Loop
    	
    							r = kyori(n_city, seq_w1, rg)
    								' 最適値の保存
    							If sw2 = 0 or r < max1
    								sw2  = 1
    								max1 = r
    								n1   = k3
    								n2   = k4
    								For i2 = 0 To n_city-1
    									seq_w5(i2) = seq_w1(i2)
    								Next
    							End If
    						End If
    					Next
    							' 最適値の保存と近傍の増加
    					If sw2 > 0
    						If max1 < max
    							sw  = 1
    							max = max1
    							For i1 = 0 To n_city-1
    								seq_w2(i1) = seq_w5(i1)
    							Next
    						End If
    						If k < neib
    							For i1 = 0 To n_city-1
    								seq_w4(i1) = seq_w5(i1)
    							Next
    							seq_w3(n1) = 1
    							seq_w3(n2) = 1
    							k1         = n2
    							k         += 1
    						Else
    							sw1 = 1
    						End If
    					Else
    						sw1 = 1
    					End If
    				Loop
    				'
    				' 近傍を固定
    				'
    			Else
    	
    				n3  = Math.Floor(rn.NextDouble() * (n_city - 2))
    				If n3 > n_city-3
    					n3 = n_city - 3
    				End If
    	                         ' 2近傍
     				i1 = 0
    				Do While i1 <= n_city-3 and ch = 0
    	
    					If n3 = 0
    						n1 = n_city - 2
    					Else
    						n1 = n_city - 1
    					End If
    	
    					i2 = n3 + 2
    					Do While i2 <= n1 and ch = 0
    	                              ' 枝の場所((n3,n3+1), (k1,k2))
    						k1 = i2
    						If i2 = n_city-1
    							k2 = 0
    						Else
    							k2 = i2 + 1
    						End If
    	                              ' 枝の入れ替え
    						seq_w1(0) = seq(n3)
    						k         = 1
    						For i3 = k1 To n3+1 Step -1
    							seq_w1(k) = seq(i3)
    							k        += 1
    						Next
    	
    						nn = k2
    						Do While nn <> n3
    							seq_w1(k) = seq(nn)
    							k        += 1
    							nn       += 1
    							If nn > n_city-1
    								nn = 0
    							End If
    						Loop
    	                              ' 評価
    						r = kyori(n_city, seq_w1, rg)
    	
    						If r < max
    							max = r
    							sw  = 1
    							For i3 = 0 To n_city-1
    								seq_w2(i3) = seq_w1(i3)
    							Next
    							If sel > 0
    								ch = 1
    							End If
    						End If
    						i2 += 1
    					Loop
    	
    					n3 += 1
    					If n3 > n_city-3
    						n3 = 0
    					End If
    					i1 += 1
    				Loop
    	                         ' 3近傍
    				If neib = 3 and ch = 0
    	
    					i1 = 0
    					Do While i1 <= n_city-3 and ch = 0
    	
    						n1 = n_city - 2
    						n2 = n_city - 1
    	
    						i2 = n3 + 1
    						Do While i2 <= n1 and ch = 0
    	
    							i3 = i2 + 1
    							Do While i3 <= n2 and ch = 0
    	                              ' 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2))
    								k1 = i3
     								If i3 = n_city-1
    									k2 = 0
    								Else
    									k2 = i3 + 1
    								End If
    	                              ' 枝の入れ替えと評価
    	                                   ' 入れ替え(その1)
    								seq_w1(0) = seq(n3)
    								k         = 1
    								For i4 = i2 To n3+1 Step -1
    									seq_w1(k) = seq(i4)
    									k        += 1
    								Next
    	
    								For i4 = k1 To i2+1 Step -1
    									seq_w1(k) = seq(i4)
    									k        += 1
    								Next
    	
    								nn = k2
    								Do While nn <> n3
    									seq_w1(k) = seq(nn)
    									k        += 1
    									nn       += 1
    									If nn > n_city-1
    										nn = 0
    									End If
    								Loop
    	                                   ' 評価(その1)
    								r = kyori(n_city, seq_w1, rg)
    	
    								If r < max
    									max = r
    									sw  = 1
    									For i3 = 0 To n_city-1
    										seq_w2(i3) = seq_w1(i3)
    									Next
    									If sel > 0
    										ch = 1
    									End If
    								End If
    	                                   ' 入れ替え(その2)
    								seq_w1(0) = seq(n3)
    								k         = 1
    								For i4 = k1 To i2+1 Step -1
    									seq_w1(k) = seq(i4)
    									k        += 1
    								Next
    	
    								For i4 = n3+1 To i2
    									seq_w1(k) = seq(i4)
    									k        += 1
    								Next
    	
    								nn = k2
    								Do While nn <> n3
    									seq_w1(k) = seq(nn)
    									k        += 1
    									nn       += 1
    									If nn > n_city-1
    										nn = 0
    									End If
    								Loop
    	                                   ' 評価(その2)
    								r = kyori(n_city, seq_w1, rg)
     	
    								If r < max
    									max = r
    									sw  = 1
    									For i3 = 0 To n_city-1
    										seq_w2(i3) = seq_w1(i3)
    									Next
    									If sel > 0
    										ch = 1
    									End If
    								End If
    	                                   ' 入れ替え(その3)
    								seq_w1(0) = seq(n3)
    								k         = 1
    								For i4 = i2+1 To k1
    									seq_w1(k) = seq(i4)
    									k        += 1
    								Next
    	
    								For i4 = i2 To n3+1 Step -1
    									seq_w1(k) = seq(i4)
    									k        += 1
    								Next
    	
    								nn = k2
    								Do While nn <> n3
    									seq_w1(k) = seq(nn)
    									k        += 1
    									nn       += 1
    									If nn > n_city-1
    										nn = 0
    									End If
    								Loop
    	                                   ' 評価(その3)
    								r = kyori(n_city, seq_w1, rg)
    	
    								If r < max
    									max = r
    									sw  = 1
    									For i3 = 0 To n_city-1
    										seq_w2(i3) = seq_w1(i3)
    									Next
    									If sel > 0
    										ch = 1
    									End If
    								End If
    	                                   ' 入れ替え(その4)
    								seq_w1(0) = seq(n3)
    								k         = 1
    								For i4 = i2+1 To k1
    									seq_w1(k) = seq(i4)
    									k        += 1
    								Next
    	
    								For i4 = n3+1 To i2
    									seq_w1(k) = seq(i4)
    									k        += 1
    								Next
    	
    								nn = k2
    								Do While nn <> n3
    									seq_w1(k) = seq(nn)
    									k        += 1
    									nn       += 1
    									If nn > n_city-1
     										nn = 0
    									End If
    								Loop
    	                                   ' 評価(その4)
    								r = kyori(n_city, seq_w1, rg)
    	
    								If r < max
    									max = r
    									sw  = 1
    									For i3 = 0 To n_city-1
    										seq_w2(i3) = seq_w1(i3)
    									Next
    									If sel > 0
    										ch = 1
    									End If
    								End If
    								i3 += 1
    							Loop
    							i2 += 1
    						Loop
    	
    						n3 += 1
    						If n3 > n_city-3
    							n3 = 0
    						End If
    						i1 += 1
    					Loop
    				End If
    			End If
    	                         ' 設定
    			If sw > 0
    				range = max
    				For i1 = 0 To n_city-1
    					seq(i1) = seq_w2(i1)
    				Next
    			End If
    	
    			Return sw
    
    		End Function
    
    	End Class
    
    End Module
    
    //------------------------ケーススタディデータ(data.txt)------
    /*
    問題の数 2
    問題 data1.txt 繰り返し回数 2
    問題 data2.txt 繰り返し回数 1
    */
    //---------------------データファイル(data1.txt)------------
    /*
    都市の数 50 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 2 Y 2 最大試行回数 1000
    86.950684 27.711487
    82.357788 16.148376
    29.791260 37.959290
    27.493286 1.542664
    90.893555 88.734436
    40.109253 92.308044
    87.445068 53.474426
    24.893188 99.382019
    11.633301 80.616760
    61.532593 8.702087
    30.645752 93.598938
    4.714966 81.205750
    86.669922 90.858459
    84.127808 52.830505
    96.893311 45.832825
    4.458618 34.513855
    53.503418 6.959534
    45.394897 12.193298
    23.687744 97.676086
    61.624146 46.806335
    49.633789 16.419983
    82.833862 74.290466
    48.529053 36.628723
    13.711548 5.583191
    12.561035 6.739807
    33.944702 26.622009
    8.917236 50.190735
    98.220825 98.344421
    79.785156 65.419006
    36.227417 56.687927
    42.352295 25.862122
    52.651978 12.590027
    88.806152 79.957581
    27.182007 51.988220
    86.334229 51.142883
    14.505005 35.820007
    77.124023 37.855530
    44.308472 0.022888
    78.363037 13.533020
    21.279907 55.534363
    82.238770 26.612854
    25.106812 88.291931
    55.938721 0.532532
    10.476685 59.233093
    41.650391 33.729553
    7.077026 4.295349
    56.561279 99.641418
    19.595337 34.416199
    92.858887 46.705627
    27.719116 35.533142
    */
    
    //---------------------データファイル(data2.txt)------------
    /*
    都市の数 10 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2
    出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt
    分割数 X 1 Y 1 最大試行回数 1000
    8.695068 2.771149
    8.235779 1.614838
    2.979126 3.795929
    2.749329 0.154266
    9.089355 8.873444
    4.010925 9.230804
    8.744507 5.347443
    2.489319 9.938202
    1.163330 8.061676
    6.153259 0.870209
    */
    			

静岡理工科大学 菅沼ホーム 目次 索引