実現したいこと
- ACが通るプログラムに修正する。
- WAになってしまう理由を理解する。
前提
AtCoderコンテスト ATC001 の A問題「深さ優先探索」の問題にチャレンジしています。
スタックを使用する等、他の解法もありますがこの質問では「なぜこのプログラムだとWAなのか」その理由を教えて欲しいです。
発生している問題・エラーメッセージ
唯一、テストケース「01_rnd_10.txt」だけWA判定になります。他のテストケースは全てAC判定です。
該当のソースコード
cpp
1#include<bits/stdc++.h> 2using namespace std; 3#define ll long long 4#define rep(i,n) for(int i = 0; i < (n); ++i) 5 6char c[500][500]; 7 8void DFS(int x, int y, int limX, int limY, bool& ans){ 9 10 if(c[y][x]=='g') { // ゴールに来た 11 ans = true; 12 return; 13 }else if(c[y][x]=='#' || x<0 || x>=limX || y<0 || y>=limY || c[y][x]=='*'){ // 壁or外or既出 14 return; 15 } 16 17 c[y][x] = '*'; 18 19 DFS(x, y-1, limX, limY, ans); 20 DFS(x+1, y, limX, limY, ans); 21 DFS(x, y+1, limX, limY, ans); 22 DFS(x-1, y, limX, limY, ans); 23} 24 25int main(){ 26 int h, w; 27 cin >> h >> w; 28 rep(i,h) rep(j,w) cin >> c[i][j]; 29 30 bool ans = false; 31 32 rep(i,h) rep(j,w) { 33 if(c[i][j] == 's') DFS(j,i,w,h,ans); 34 } 35 36 cout << (ans ? "Yes" : "No") << endl; 37 return 0; 38}
試したこと
ChatGPTやbingAIに質問しましたが、期待していた出力は得られませんでした。
(この手のどこぞの問題の話を持ってくる人って,何故問題へのリンクを示さないのだろう?)
ごめんなさい...!これがリンクです!
https://atcoder.jp/contests/atc001/tasks/dfs_a
> 01_rnd_10.txt
とかいうやつの内容をどこから見れるのか探せなかったが,それはそれとして,
関数 DFS() の実装はこれだと範囲外参照しまくりなのでは? と見える
(:(x,y) が範囲内にあるか否かの判定よりも先に c[y][x] にアクセスしてる)ので,
他の入力例で正解になる方が「たまたま」なのではなかろうか.
あと,ゴールが見つかっても探索を打ち切らないのは効率悪そう.
> 先に c[y][x] にアクセスしてる
念のために言っておくが
先頭のゴールの判定だけじゃなくて,その後の else if もだよ.
(後者側がピンとこない場合には 「短絡評価(ショートサーキット)」 とかでググると良いかと)
範囲外判定をDFS()の最初に行うように変更したらACになりました...。
とても納得できました、ありがとうございます!
範囲外参照しっかり意識したいと思います...。
ちなみになのですが、この書き方の様な再帰関数の場合、ゴールが見つかった時点で他の探索を打ち切るというのは、DFS()の先頭に if(ans) return; を書いておけば良いという認識で良いでしょうか?
> DFS()の先頭に if(ans) return; を書いておけば良い
とりあえずそれで良いと思います.
それはそれとして,
「ans を引数にとってそれを書き換える」という形にする必要が特段無いならば,結果を return で返す形の関数とするほうが素直(?)であるように思います.
で,DFS() 内末尾での4つの DFS() 呼び出しのところを
return ( DFS(x,y-1) || DFS(x+1,y) || DFS(x,y+1) || DFS(x-1,y) );
のように書くとか.(ここもまたショートサーキットになるので,いずれかがtrueを返してきた時点で後ろ側のDFS()呼び出しは成されない:探索の打ち切り)
ありがとうございます。勉強になりました。
問題が解決した場合には,この質問を何かしら適切な形で解決状態にしてください.
(ヘルプを見るに,「回答」が付いていない段階で問題が解決した場合には自己解決の形をとるのが良い様子です)

回答1件
あなたの回答
tips
プレビュー