質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
アルゴリズム

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

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1809閲覧

優先度付きキューを利用したダイクストラ法のアルゴリズムのプログラムを作成したいです。

wagashi_157

総合スコア51

アルゴリズム

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

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/11/13 04:53

編集2021/11/15 21:15

前提・実現したいこと

以下の要領を基に優先度付きキューを適切に利用したダイクストラ法のアルゴリズムを実装しようと思っています。

  1. まず,30個の頂点上のグラフを保持する二次元配列graph[N][N],及び,その隣接リストvList[N],更に,最短経路木を保持する一次元配列path[N] を(大域変数として)用意する.
  2. グラフG = (V,E) をランダムに生成する.(巻末の付録を参照.)そのグラフを出力する.(これらを関数gen_graph(), print_graph() で行う.)
  3. 優先度付きキューを初期化する.(これを関数init_heap() で行う.)
  4. 始点をs = 0,終点をt = 29 として,s からt への(G 上の)最短経路をダイクストラのアルゴリズムで探索する.(これを関数dijkstra() で行う.)
  5. 到達可能であればpath が示す経路を「始点から順に」出力する.(配列pathは,終点から辿っていかざるをえず,それを順に表示すると逆順になってしまう!スタックか再帰を用いると解決できる.)到達不可能であればその旨を出力する.(グラフはランダム生成なためそういう場合もある.)

発生している問題・エラーメッセージ

push,pop,changeのプログラムは解決できましたが, 到達可能を判定するためのrec_print_pathの表現の仕方が分からず困っています(print_pathにもあるようにvoid関数で実装したいです)。それとlist関数を使ってdijkstra()を実装したいのですが, イテレータで表現してもエラーが出てしまい, 原因が分かりません。イテレーターに慣れていないのとダイクストラ法で図は描けるもののプログラムとなると中々上手くいかないので教えてほしいです。

dijkstra.cpp: 関数 ‘void dijkstra()’ 内: dijkstra.cpp:151:66: エラー: no match for ‘operator[]’ (operand types are ‘int [30][30]’ and ‘std::_List_iterator<to_len>’) if ((*it).len+graph[s][j]<(*it).len) (*it).len=(*it).len+graph[it][j]; ^ dijkstra.cpp:156:40: エラー: no match for ‘operator=’ (operand types are ‘std::_List_iterator<to_len>’ and ‘int’) if ((*it).len<minlen) {minlen=j; it=j;} ^ In file included from /usr/lib/gcc/i686-pc-cygwin/7.4.0/include/c++/list:63:0, from dijkstra.cpp:3: /usr/lib/gcc/i686-pc-cygwin/7.4.0/include/c++/bits/stl_list.h:128:12: 備考: candidate: constexpr std::_List_iterator<to_len>& std::_List_iterator<to_len>::operator=(const std::_List_iterator<to_len>&) struct _List_iterator ^~~~~~~~~~~~~~ /usr/lib/gcc/i686-pc-cygwin/7.4.0/include/c++/bits/stl_list.h:128:12: 備考: 第 1 引数を ‘int’ から ‘const std::_List_iterator<to_len>&’ へ変換する方法が不明です /usr/lib/gcc/i686-pc-cygwin/7.4.0/include/c++/bits/stl_list.h:128:12: 備考: candidate: constexpr std::_List_iterator<to_len>& std::_List_iterator<to_len>::operator=(std::_List_iterator<to_len>&&) /usr/lib/gcc/i686-pc-cygwin/7.4.0/include/c++/bits/stl_list.h:128:12: 備考: 第 1 引数を ‘int’ から ‘std::_List_iterator<to_len>&&’ へ変換する方法が不明です

該当のソースコード

C++

1#include<iostream> 2#include<random> 3using namespace std; 4 5#define N 30 6#define DENSITY 9 7#define MAX_COST 100 8 9struct node { 10 int id; 11 int cost; 12}; 13struct to_len { 14 int to, len; 15}; 16list<to_len> vList[N]; 17 18node node_data[N]; 19int node_idx[N]; 20int heap_size; 21 22void gen_node_data() 23{ 24 mt19937 mt{random_device{}()}; 25 uniform_int_distribution<int> dist(0,MAX_COST); 26 heap_size = 0; 27 28 for (int i=0; i<N; i++) { 29 node_data[i].id = i; 30 node_data[i].cost = dist(mt); 31 heap_size++; 32 33 node_idx[i] = i; 34 } 35} 36 37int left(int i) {return 2*i+1;} 38int right(int i) {return 2*i+2;} 39void swap(node &a, node &b) {node tmp=a; a=b; b=tmp;} 40 41void down_heap(int parent) 42{ 43 if (left(parent)>heap_size-1) return; 44 45 if (left(parent)==heap_size-1) { 46 if (node_data[parent].cost>node_data[left(parent)].cost) { 47 node_idx[node_data[parent].id] = left(parent); 48 node_idx[node_data[left(parent)].id] = parent; 49 swap(node_data[parent],node_data[left(parent)]); 50 down_heap(left(parent)); 51 } 52 } else { 53 if (node_data[left(parent)].cost<=node_data[right(parent)].cost) { 54 if (node_data[parent].cost>node_data[left(parent)].cost) { 55 node_idx[node_data[parent].id] = left(parent); 56 node_idx[node_data[left(parent)].id] = parent; 57 swap(node_data[parent],node_data[left(parent)]); 58 down_heap(left(parent)); 59 } 60 } else { 61 if (node_data[parent].cost>node_data[right(parent)].cost) { 62 node_idx[node_data[parent].id] = right(parent); 63 node_idx[node_data[right(parent)].id] = parent; 64 swap(node_data[parent],node_data[right(parent)]); 65 down_heap(right(parent)); 66 } 67 } 68 } 69} 70void up_heap(int child) 71{ 72 int parent=(child-1)/2; 73 if (child>heap_size-1) return; 74 75 if (child==heap_size-1) { 76 if (node_data[parent].cost<node_data[child].cost) { 77 node_idx[node_data[parent].id] = child; 78 node_idx[node_data[child].id] = parent; 79 swap(node_data[parent],node_data[child]); 80 up_heap(parent); 81 } 82 } else { 83 if (node_data[right(parent)].cost<=node_data[left(parent)].cost) { 84 if (node_data[left(parent)].cost>node_data[parent].cost) { 85 node_idx[node_data[parent].id] = left(parent); 86 node_idx[node_data[left(parent)].id] = parent; 87 swap(node_data[parent],node_data[left(parent)]); 88 up_heap(parent); 89 } 90 } else { 91 if (node_data[right(parent)].cost>node_data[parent].cost) { 92 node_idx[node_data[parent].id] = right(parent); 93 node_idx[node_data[right(parent)].id] = parent; 94 swap(node_data[parent],node_data[right(parent)]); 95 up_heap(parent); 96 } 97 } 98 } 99} 100void make_heap() 101{ 102 for (int i=(N-1)/2; i>=0; i--) { 103 down_heap(i); 104 } 105} 106bool check_rightmost(int i) 107{ 108 int x = i+2; 109 while (x>1) { 110 if (x%2==1) return 0; 111 else x=x/2; 112 } 113 return 1; 114} 115void push(int id, int cost) 116{ 117 for (int i=0; i<N-1; i++) { 118 node_data[i].id=node_data[i+1].id; 119 node_data[i].cost=node_data[i+1].cost; 120 } 121 for (int i=0; i<N-1; i++) { 122 node_idx[node_data[i].id]=node_data[i].id; 123 } 124 node_data[N-1].id=id; 125 node_data[N-1].cost=cost; 126 node_idx[node_data[N-1].id]=node_data[N-1].id; 127} 128 129void pop() 130{ 131 for (int i=0; i<N-1; i++) { 132 node_data[i].id=node_data[i+1].id; 133 node_data[i].cost=node_data[i+1].cost; 134 } 135 for (int i=0; i<N-1; i++) { 136 node_idx[node_data[i].id]=node_data[i].id; 137 } 138 node_idx[node_data[N-1].id]=node_data[N-1].id; 139} 140void change(int id, int cost) 141{ 142 int old; 143 old=node_data[node_idx[id]].cost; 144 node_data[node_idx[id]].cost=cost; 145 if (old>node_data[node_idx[id]].cost) down_heap(node_idx[id]); 146 else up_heap(node_idx[id]); 147} 148void print_path() 149{ 150 if (path[N-1] == -1) 151 cout << "Unreachable!" << endl; 152 else { 153 rec_print_path(N-1); 154 cout << endl; 155 cout << "cost: " << node_data[0].cost << endl; 156 } 157} 158 159void rec_print_path(int vertex) 160{ 161 path[0]=1; 162 for (auto next:graph[vertex]) { 163 if (path[next]==1) continue; 164 rec_print_path(next); 165 } 166} 167int main() 168{ 169 gen_graph(); 170 print_graph(); 171 172 init_heap(); 173 dijkstra(); 174 175 print_path(); 176 177 return 0; 178} 179

試したこと

イテレーターであるため, print_graph()を参考にdijkstra()を作成しました。rec_print_pathではfor(auto ...)を使って順に判定してみました。

補足情報(FW/ツールのバージョンなど)

C++17を利用しています。

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

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

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

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

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

Zuishin

2021/11/14 05:39

C++ でこんな機械的に回答できるものに何の反応もないなんて何をしたんだろうと思って質問一覧を見たら、見るからに課題の丸投げを連発してる人だった。 無理な課題ならやらなくていいのでは?
actorbug

2021/11/14 09:31

まずは、以前のソースからleft,right関数の定義をコピペして、dijkstra関数の閉じカッコが足りないのを直しましょう。 あとは、コピペするなとは言いませんが、せめて内容を説明できるぐらいに理解してからにしましょう。 push関数で、どのような処理が必要なのか、日本語で説明できますか? できないようなら、「ヒープ 追加」などで検索して、どういう原理で動作するのか理解しましょう。
actorbug

2021/11/14 20:40

正直、push,pop,changeすべて間違っています。(ついでにいうとup_heapも) changeはコードが足りない程度ですが、push,popはやろうとしていること自体が間違っています。 まずは、優先度付きキュー単独で正しく動作するところまで作りこむことをお勧めします。 削除依頼の出ている一つ前の質問のコードがまともに動作するまで、dijkstraには手を出さない方がよいでしょう。
wagashi_157

2021/11/15 09:31

push,popはstackやqueueだとそのまま入力すれば実装できますが, int型配列だとどのように表現すれば良いかを考えたときにインターネットで調べたことも含め「値の更新を行う」ことしか思いつきませんでした。 優先度付きキューだとアップヒープも含めプログラムのどこに違いがあるのかを教えてほしいです。
actorbug

2021/11/15 13:40 編集

なぜ間違っていなかったdown_heapを消して、make_heapを誤ったものに書き換えてしまったのでしょうか。 あと、インターネットで調べて「思いついた」内容を実装するのではなく、インターネットで正しいやり方を調べて、それを実装してください。 このページのP21以降の説明と疑似コードなど参考にならないでしょうか。 http://www.sd.is.uec.ac.jp/koga/lecture/FSkiso1/kiso1_04.pdf
guest

回答1

0

自己解決

ダイクストラ法のwebサイトを参考にしたら何とかできました。

投稿2021/11/18 01:43

wagashi_157

総合スコア51

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問