C言語関係掲示板

過去ログ

No875 最長経路を求める

[戻る] [ホームページ]
No.11357

最長経路
投稿者---とっと(2003/12/20 20:30:41)


次のような隣接行列があったときに
weight[n][m] (n→mの経路があるときはその距離がはいる)

ソースからシンクまでの経路のなかで
最長経路を求めるよなプログラムを作りたいのですが
うまくいきません。
なにか良い方法はないでしょうか?


No.11369

Re:最長経路
投稿者---あかま(2003/12/21 01:59:31)


最"長"経路?
a→b→c→a...みたいな経路があったら、無限に飛んじゃうけどええのん?

No.11379

Re:最長経路
投稿者---kikk(2003/12/21 20:07:58)


ども。


>最長経路を求めるよなプログラムを作りたいのですが
>なにか良い方法はないでしょうか?

最長経路問題は、良い方法はないとされる問題の1つだったと思います。
詳細はNP問題関連を調べてみてください。

解ければいいのであれば、以下のような総当りの方法でよろしいかと。

1) 全ノードに番号が振ってあると仮定。
2) 起点と終点を除くノード番号による、全ての順列を生成する。
 (ノード数5、起点ノード番号1、起点ノード番号5なら、
 234, 243, 324, 342, 423, 432)
3) それぞれに対し起点と終点を付加する。
 (324についてなら、13245となる)
4-1) 3)で生成したパスに対し、切れていないかを調べ、
 (1から3、3から2、2から4、4から5が到達可能であるかをチェック)
4-2) 切れてなければ、ノード間の重みを合計して全経路長を取得し、
それが最長かを調べる。

順列は、1回しか参照しないので、最初に全部作る必要はありません。
生成しながら上記3〜4を行ってください。全ての順列の生成方法は
過去ログのどこかにあるかもしれません(投稿した憶えがあるので)。
あと、必要があれば枝刈りを行ってください。


では。

No.11421

Re:最長経路
投稿者---あかま(2003/12/22 23:14:23)


恥ずかしい勘違いをしちゃったっぽいのでプログラムを書いてみる。
#include<stdio.h>
#define MAX 100

int MAT_NUM,matrix[MAX][MAX];//ノード数,行列
int matset[MAX],junjo[MAX];//使用したノードの保存,確定した順序の保存
int max_junjo[MAX],max_value;//最大値を記録した順序,最大値
int branch;//派生した枝の数

search(int deep){
    int i,value;
    deep++;
    if(deep < MAT_NUM-1){//順序が全て確定してないとき
        for(i = 0;i < MAT_NUM;i++){
            if(matset[i] == 0){
                branch++;
                junjo[deep] = i;
                matset[i] = 1;
                search(deep);
                matset[i] = 0;
            }
        }
    }
    else{//順序が全て確定した
        for(i = 1,value=0;i < MAT_NUM;i++) value += matrix[junjo[i-1]][junjo[i]];
        //for(i = 0;i < MAT_NUM;i++) {printf("->%d",junjo[i]);}printf("  value=%d\n",value);//途中経過の表示
        if(value > max_value){
            max_value = value;
            for(i = 0;i < MAT_NUM;i++) max_junjo[i] = junjo[i];
        }
    }
    
    
}
main(){
    
    int i,j;
    
    /***読み込み開始***/
    scanf("%d",&MAT_NUM);
    //始点と終点のセット
    scanf("%d %d",&junjo[0],&junjo[MAT_NUM-1]);
    matset[junjo[0]] = 1;
    matset[junjo[MAT_NUM-1]] = 1;
    //行列のセット
    for(i = 0;i < MAT_NUM;i++){
        for(j = 0;j < MAT_NUM;j++){
            scanf("%d",&matrix[i][j]);
        }
    }
    
    //探索開始
    search(0);
    
    //結果の表示
    printf("枝の数は%d\n",branch);
    printf("%d - %d 間の最長経路は\n",junjo[0],junjo[MAT_NUM-1]);
    for(i = 0;i < MAT_NUM;i++){
        printf("->%d",max_junjo[i]);
    }
    printf("\n最大値は%d\n",max_value);
}

入力はリダイレクトでファイルから。↓のようなフォーマット。
ノード数
始点 終点
以下ノードの行列

5
0 4
2 6 9 4 0 
2 1 7 0 3 
6 5 9 0 5 
6 8 8 3 4 
9 7 1 4 7 

0->1->2->3->4の順序でノードを通るなら
6+7+0+4=17となる。
でもこの全件探索プログラムだとノード数13ぐらいが限界でした。その時点で枝の数1億突破。
枝刈したいけど、どうやったらできるんだー???
明日がんばってみよう。


No.11423

Re:最長経路
投稿者---あかま(2003/12/22 23:19:59)


ついでに行列作成プログラム
保存するファイル名、ノードの数、始点終点の入力で↓のようなのランダムに作ってくれます。

5
0 4
2 6 9 4 0 
2 1 7 0 3 
6 5 9 0 5 
6 8 8 3 4 
9 7 1 4 7 


#include <stdio.h>
#include <stdlib.h>

main(){
    int kosu,i,j,begin,end;
    char filename[128];
    FILE *fp;
    
    printf("保存するファイル名は?\n");
    scanf("%s",filename);
    srand(time(NULL));
    printf("ノードの個数は?\n");
    scanf("%d",&kosu);
    printf("始点と終点は?[0〜%d]\n",kosu-1);
    scanf("%d %d",&begin,&end);
    
    fp = fopen(filename,"w");
    
    fprintf(fp,"%d\n%d %d\n",kosu,begin,end);
    for(i=0;i < kosu;i++){
        for(j=0;j < kosu;j++){
            fprintf(fp,"%d ",rand()%10);
        }
        fprintf(fp,"\n");
    }
    
    fclose(fp);
    printf("作成終了");
}



No.11466

Re:最長経路
投稿者---とっと(2003/12/26 15:23:20)


わざわざ、プログラムまで書いていただき
ありがとうございました。

とりあえず、これを参考に作ってみたいと思います