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

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

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

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

C++

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

Q&A

解決済

2回答

2183閲覧

C++のメッセージ無しでの強制終了で困っています

chan_yu1224

総合スコア7

アルゴリズム

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

C++

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

0グッド

1クリップ

投稿2019/08/21 07:40

編集2019/08/21 08:16

はじめまして,今回が本サイトでの初めての質問になります.
最近競技プログラミングを始めるためにC++を勉強しているのですが,言語仕様が分からない故のバグに日々悩まされています.

AtcoderTypicalContest001 A問題「深さ優先探索」のためのソースコード(下記)についてなのですが,
'#'を塀,'.'を道としてスタート地点('s')からゴール地点('g')までたどり着くことが出来るかどうかを判定する問題です.
以下のソースコード及びテストパターンにおいて,何らかのメッセージも無しに強制終了してしまいます.
最終的に"Yes"もしくは"No"を返すはずだと思うのですが出力が出てくれません.

強制終了の原因もしくは解決策があれば教えて頂きたいです.

OSはwindows,開発環境はvisual studio codeを使用しています.

###ソースコード

C++

1#include <bits/stdc++.h> 2 3#define rep(i, n) for(int i = 0; i < (int)(n); i++) 4#define repr(i, n) for(int i = (int)(n); i >= 0; i--) 5#define repm(i, m, n) for(int i = (int)(m); i < (int)(n); i++) 6#define repmr(i, m, n) for(int i = (int)(n); i >= (int)(m); i--) 7#define all(x) (x).begin(),(x).end() 8#define inf 2e9 9 10using namespace std; 11typedef long long int lli; 12typedef long long ll; 13 14int main() { 15 int h,w; 16 cin >> h >> w; 17 vector<vector<char>> c(h, vector<char>(w)); 18 vector<int> start(2); 19 rep(i,h) rep(j,w){ 20 cin >> c[i][j]; 21 if(c[i][j] == 's'){ 22 start[0] = i; 23 start[1] = j; 24 } 25 } 26 27 vector<vector<bool>> rout(h, vector<bool>(w, false)); 28 stack<vector<int>> st; 29 st.push(start); 30 bool goal = false; 31 while(st.size() != 0){ 32 vector<int> now = st.top(); 33 if(c[now[0]][now[1]] == 'g'){ 34 goal = true; 35 break; 36 } 37 st.pop(); 38 rout[now[0]][now[1]] = true; 39 if(now[0]-1 >= 0 && c[now[0]-1][now[1]] != '#' && !rout[now[0]-1][now[1]]){ 40 st.push({now[0]-1, now[1]}); 41 cout << st.top()[0] << " " << st.top()[1] << endl; 42 } 43 if(now[0]+1 < h && c[now[0]+1][now[1]] != '#' && !rout[now[0]+1][now[1]]){ 44 st.push({now[0]+1, now[1]}); 45 cout << st.top()[0] << " " << st.top()[1] << endl; 46 } 47 if(now[1]-1 >= 0 && c[now[0]][now[1]-1] != '#' && !rout[now[0]][now[1]-1]){ 48 st.push({now[0], now[1]-1}); 49 cout << st.top()[0] << " " << st.top()[1] << endl; 50 } 51 if(now[1]+1 < w && c[now[0]][now[1]+1] != '#' && !rout[now[0]-1][now[1]+1]){ 52 st.push({now[0], now[1]+1}); 53 cout << st.top()[0] << " " << st.top()[1] << endl; 54 } 55 } 56 57 cout << ((goal) ? "Yes":"No") << endl; 58 59}

入力内容

4 4 ...s .... .... .g..

出力内容

stackにpushする内容を毎回出力しています.

1 3 0 2 1 2 0 1

ここで出力が途切れ,何のメッセージもなく強制終了します.

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

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

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

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

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

showkit

2019/08/21 08:01

オペレーティングシステムは何を使用していますか? Unix/Linux 系であれば、デバッグモードで make して core を出力させれば、デバッガでどこで こけたかを確認できますが・・・。
tacsheaven

2019/08/21 08:08

実際に Linux 上で gcc(g++) でコンパイルして動かすと Segmentation Fault 起こしますね。
chan_yu1224

2019/08/21 08:11

OSはWindowsなので確認できないです... 開発環境はVSCodeを使用しています. VisualStudioでウォッチを使いたいのですが今容量不足で入れることが出来ないので...
guest

回答2

0

ベストアンサー

このプログラムの探索アルゴリズムを見てみましょう。

stack に push されている内容は、現在の座標位置を表しています(y, x の順のようですが)
そして探索の手順として、

  1. 現在位置の上が座標外ではなく、堀でもなく、探索済み(rout[][] が true)でもないなら、現在位置を一つ上へずらす
  2. 現在位置の下が座標外ではなく... なら、現在位置を一つ下へずらす
  3. 現在位置の左が座標外ではなく... なら、現在位置を一つ左へずらす
  4. 現在位置の右が座標外ではなく... なら、現在位置を一つ右へずらす

これを踏まえた上で読むと、一カ所おかしなところがあります。

CPP

1 while(st.size() != 0){ 2 vector<int> now = st.top(); 3 if(c[now[0]][now[1]] == 'g'){ 4 goal = true; 5 break; 6 } 7 st.pop(); 8 rout[now[0]][now[1]] = true; 9 if(now[0]-1 >= 0 && c[now[0]-1][now[1]] != '#' && !rout[now[0]-1][now[1]]){ 10 st.push({now[0]-1, now[1]}); 11 cout << st.top()[0] << " " << st.top()[1] << endl; 12 } 13 if(now[0]+1 < h && c[now[0]+1][now[1]] != '#' && !rout[now[0]+1][now[1]]){ 14 st.push({now[0]+1, now[1]}); 15 cout << st.top()[0] << " " << st.top()[1] << endl; 16 } 17 if(now[1]-1 >= 0 && c[now[0]][now[1]-1] != '#' && !rout[now[0]][now[1]-1]){ 18 st.push({now[0], now[1]-1}); 19 cout << st.top()[0] << " " << st.top()[1] << endl; 20 } 21 if(now[1]+1 < w && c[now[0]][now[1]+1] != '#' && !rout[now[0]-1][now[1]+1]){ 22 st.push({now[0], now[1]+1}); 23 cout << st.top()[0] << " " << st.top()[1] << endl; 24 } 25 } 26

問題はこの if 群の4番目にあります。
探索済みかどうかは、動く「先」を確認するものですから、rout[now[0]-1][now[1]+1] はおかしいですね。
rout[now[0]][now[1]+1] でないといけないはずです。

結果どうなるかというと、四歩目の時点で (0, 1) にいますから、五歩目として rout[-1][2] を見ようとして、範囲外アクセスが起きて Segmentation fault になりますね。

投稿2019/08/21 08:33

tacsheaven

総合スコア13703

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

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

chan_yu1224

2019/08/21 08:39

回答ありがとうございます. 完全に確認を怠っておりました....(お恥ずかしい) 言語仕様の問題以前の問題でした. 次からは気を付けてコーディングします. ありがとうございました!
tacsheaven

2019/08/21 08:45

ちなみに三歩目のとき((1,3)->(0,2) の次)のときは、nowが(0,3)であるため、now[1]+1 < w の条件が満たされず rout へのアクセスが行われなかったために Segmentation Fault にならないのです。
guest

0

落ちた所とウォッチした値を貼っておきます。
イメージ説明

投稿2019/08/21 08:41

takabosoft

総合スコア8356

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問