teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

add

2018/07/13 14:50

投稿

papinianus
papinianus

スコア12705

answer CHANGED
@@ -1,2 +1,115 @@
1
1
  List<T>を普通に比較したら、参照の比較になって同じインスタンスの参照でなければ、同値にはならないですね。
2
- ValueTupleにするか、クラス作ってIEquatable実装するか、!visited.Any(v=>v.SequenceEqual(next))みたいなラムダをかくかってとこですかね。
2
+ ValueTupleにするか、クラス作ってIEquatable実装するか、!visited.Any(v=>v.SequenceEqual(next))みたいなラムダをかくかってとこですかね。
3
+
4
+ --解決したみたいなので蛇足
5
+ まず、visual studioを使ってください。C#はvisual studioがあってこそです。vsという解決策があるのに、エラーをコンパイルまで気付けないというのは大切な時間を無駄にしています(vs communityは個人の非商用とかを条件に無償で使えます)。
6
+
7
+ IEquatableはやろうとしていることに対して手間がかかりすぎる提案でした。
8
+ 提示いただいた入力例ではおそらくバグは発生せずに、abaみたいなものをyesにするのが問題だと理解しました。以前に書いていたラムダの件を反映したコードが↓
9
+ ```csharp
10
+ using System;
11
+ using System.Collections.Generic;
12
+ using System.Linq;
13
+ using System.Text;
14
+ using System.Threading.Tasks;
15
+ using System.Collections;
16
+ using static System.Console;
17
+
18
+ public class Program
19
+ {
20
+ public static int[] dx = { -1, 0, 1, 0 };
21
+ public static int[] dy = { 0, 1, 0, -1 };
22
+ public static int N;
23
+ public static char[][] map;
24
+ public static string str;
25
+
26
+ public static bool dfs(Stack<List<int>> visited, int y, int x, int count)
27
+ {
28
+ if (count == str.Length)
29
+ {
30
+ return true;
31
+ }
32
+ else
33
+ {
34
+ for (int i = 0; i < 4; i++)
35
+ {
36
+ int ny = y + dy[i];
37
+ int nx = x + dx[i];
38
+ List<int> next = new List<int> { ny, nx };
39
+ if (nx < 0 || nx >= N || ny < 0 || ny >= N)
40
+ {
41
+ continue;
42
+ }
43
+ else if (map[ny][nx] == str[count] && !visited.Any(v=>v.SequenceEqual(next)))
44
+ {
45
+ visited.Push(next);
46
+ count += 1;
47
+ if (dfs(visited, ny, nx, count))
48
+ {
49
+ return true;
50
+ }
51
+ else
52
+ {
53
+ count -= 1;
54
+ visited.Pop();
55
+ }
56
+ }
57
+ }
58
+ return false;
59
+ }
60
+ }
61
+ public static void Main()
62
+ {
63
+ // Your code here!
64
+ N = int.Parse(Console.ReadLine());
65
+ map = new char[N][];
66
+ for (int i = 0; i < N; i++)
67
+ {
68
+ map[i] = Console.ReadLine().ToCharArray();
69
+ }
70
+ int M = int.Parse(Console.ReadLine());
71
+ for (int i = 0; i < M; i++)
72
+ {
73
+ str = Console.ReadLine();
74
+ bool writable = false;
75
+ var visited = new Stack<List<int>>();
76
+ for (int j = 0; j < N; j++)
77
+ {
78
+ for (int k = 0; k < N; k++)
79
+ {
80
+ if (str[0] == map[j][k])
81
+ {
82
+ List<int> next = new List<int> { j, k };
83
+ visited.Push(next);
84
+ int count = 1;
85
+ if (dfs(visited, j, k, count))
86
+ {
87
+ System.Console.WriteLine("yes");
88
+ writable = true;
89
+ break;
90
+ }
91
+ else
92
+ {
93
+ count -= 1;
94
+ visited.Pop();
95
+ }
96
+ }
97
+ }
98
+ if (writable)
99
+ {
100
+ break;
101
+ }
102
+ }
103
+ if (!writable)
104
+ {
105
+ System.Console.WriteLine("no");
106
+ }
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ ただ、こういう場合visitedをStack<List<int>>にするのではなく、stringにすればいいのではないかと思います(`next = j + "," + k;`のように)。そうすればvisited.Containsで判断してくれるはず。
113
+ もしくはもう少しOOPにするなら、`struct Positon { int x { get; set; } int y { get; set; } }`を定義しておいて、`next = new Positon() { x = j, y = k };`でもいいかもしれないです(visitedはStack<Position>型)。structは等値比較が暗黙に定義されるので。
114
+
115
+ 用途からすると文字列にするのがてっとりばやいと思います。(ちなみに string next = j + k;としてしまうと111が、1,11なのか11,1なのか識別できなくなるので、","みたいなjやkでは絶対に出てこない区切りを入れるといいかと思います)

1

修正

2018/07/13 14:50

投稿

papinianus
papinianus

スコア12705

answer CHANGED
@@ -1,2 +1,2 @@
1
1
  List<T>を普通に比較したら、参照の比較になって同じインスタンスの参照でなければ、同値にはならないですね。
2
- ValueTupleにするか、クラス作ってIEquatable実装するか、!visited.Any(v=>v.ElementAt(0)==next.ElementAt(0)&&v.ElementAt(1)==next.ElementAt(1))みたいなラムダをかくかってとこですかね。
2
+ ValueTupleにするか、クラス作ってIEquatable実装するか、!visited.Any(v=>v.SequenceEqual(next))みたいなラムダをかくかってとこですかね。