ABC - 054 - A&B&C

#AtCoder ABC 054 A&B&C
[AtCoder - 054](https://atcoder.jp/contests/abc054)

#A問題

 - AとBの数を比べる
 - 2<3<4<5<6<7<8<9<10<11<12<13<1 の順
 - 同じ数ならDraw
 - 1が最強なのでどちらかが1だったら其方の勝ち
 - 同じ数でもなく、1でもないなら数が大きいほうが勝ち

```java
		int alice = nextInt();
		int bob = nextInt();

		if (alice == bob) {
			out.println("Draw");
		} else if (alice == 1) {
			out.println("Alice");
		} else if (bob == 1) {
			out.println("Bob");
		} else if (alice != bob) {
			out.println(alice > bob ? "Alice" : "Bob");
		}

		out.println("");
````

---
#B問題

 説明はソースにインラインで記載

```java

	private void solveB() {
		int numN = nextInt();
		int numM = nextInt();
		String[] wkA = new String[numN];
		String[] wkB = new String[numM];

		for (int i = 0; i < wkA.length; i++) {
			wkA[i] = next();
		}
		for (int i = 0; i < wkB.length; i++) {
			wkB[i] = next();
		}

		boolean res = chkB(wkA, 0, wkB, 0);
		out.println(res ? "Yes" : "No");
	}


	private boolean chkB(String[] wkA, int currentA, String[] wkB, int aPos) {
		boolean res = false;

		//wkAの残りがwkBより少ない場合は探索できない
		if (wkA.length - currentA < wkB.length) {
			return false;
		}
		//wkA[]の残り長がwkB[]より少ない場合は探索できない
		if (wkA[currentA].length() - aPos < wkB[0].length()) {
			return false;
		}
		//まず、Aの位置を決める
		//そのために、BのcurrentB列目がAのcurrentA列目どこに出現するのか確認
		//Aの横軸の値を取得
		//※Aの横軸は複数取得できる可能性がある。
		//BのcurrentB列目がAのcurrentA列目どこに出現するのか確認
		boolean aPosWk = wkA[currentA].startsWith(wkB[0], aPos);
		if (aPosWk) {
			//Aの横軸出現したらcurrentA+1の列の横軸から、B列のcurrentB+1が出現するのか確認

			for (int i = 0; i < wkB.length; i++) {
				res = wkA[currentA + i].startsWith(wkB[0 + i], aPos);
				if (!res) {
					break;
				}
			}

		}
		//Aの横軸が出現しなかったら、aPos+1列目を検索
		//このaPosでは一致しない場合、aPosを+1して再探索
		if (!res) {
			//B列のcurrentB+1が出現しなかったら、もう一度、Aの横軸を検索
			int len = wkA[currentA].indexOf(wkB[0], aPos + 1);
			//横列にまだ候補があるので再検索
			if (len >= 0) {
				res = chkB(wkA, currentA, wkB, len);
			}

		}

		//aPosが0でない場合は次のcurrentIdを
		if (!res && aPos == 0) {
			//Aの横軸が出現しなかったら、currentA+1行目を検索
			res = chkB(wkA, currentA + 1, wkB, 0);
		}
		return res;
	}
```

#C問題
無向グラフ
[参考:1](https://boostjp.github.io/archive/boost_docs/libs/graph/graph_theory_review.html)
[参考:2](http://can.hatenadiary.com/entry/2016/02/17/221604)

とりあえず、入力例1を隣接行列として表現する。

###入力1
>1 2
>1 3
>2 3

変換(行ける所にTrueをはめる)

|      |1     |2     |3     |
|:----:|:----:|:----:|:----:|
|1     |      |T     |T     |
|2     |T     |      |T     |
|3     |T     |T     |      |


無向グラフなので対象行列となる。

  - まずは、入力を対象行列に変換
  - 行ける位置にtrueを代入
  - 行った先をmemoするために、numNと同じ長さのboolean[]を生成
  - 検索自体は再帰で行う
  - 最初の1か所目は訪れ済み

```java

	private void solveC() {

		int numN = nextInt();
		int numM = nextInt();

		boolean[][] wk = new boolean[numN][numN];

		for (int i = 0; i < numM; i++) {
			int iA = nextInt();
			int iB = nextInt();
			wk[iA - 1][iB - 1] = true;
			wk[iB - 1][iA - 1] = true;
		}
		boolean[] visited = new boolean[numN];
		visited[0] = true;
		int res = chkSolveC(wk, 0, visited);
		out.println(res);
	}

```
 - 再帰の終了条件
    - すでに訪れたところがあるなら+1して終了
 - 次に進む条件
    - 隣接行列上行ける(wk[][]でtrue)　＆　まだ訪れたことが無い(visited[]でfalse)

再帰だとchkSolveCを呼び出す際にcurrentIを+1したくなったけど、よく考えたら隣接行列で行ける所のiを取り出して引数のcurrentIとして渡しているので+1なんて不要。

```java

	private int chkSolveC(boolean[][] wk, int currentI, boolean[] visited) {

		boolean res = true;
		for (int i = 0; i < visited.length; i++) {
			if (!visited[i]) {
				res = false;
			}
		}
		if (res) {
			return 1;
		}

		int resCnt = 0;
		boolean[] wkG = wk[currentI];
		for (int i = 0; i < wkG.length; i++) {
			if (wkG[i] && !visited[i]) {
				visited[i] = true;
				resCnt += chkSolveC(wk, i, visited);
				visited[i] = false;
			}

		}

		return resCnt;
	}
```