1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ABC - 054 - A&B&C

Last updated at Posted at 2019-03-24

AtCoder ABC 054 A&B&C

AtCoder - 054

A問題

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

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


	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
参考:2

とりあえず、入力例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か所目は訪れ済み

	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なんて不要。


	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;
	}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?