LoginSignup
0
0

More than 1 year has passed since last update.

ABC244A~Dの解答[Java]

Last updated at Posted at 2022-09-14

はじめに

初めて4完したコンテストですね。懐かしい。
なお、コードは当時提出したものと簡単に書き直したものの二つを載せます。

では、見ていきましょう。

A - Last Letter

問題文はこちら

そのままですね。
0-indexedであることに注意しましょう。

A.java
import java.io.*;
class Main{
	public static void main(String[] args)throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		//Nは使わない
		String decoy = br.readLine();

		//Sの受け取り
		String str = br.readLine();

		//末尾だけ切り出して出力
		System.out.println(str.substring(str.length()-1));
	}
}

書き直すならこんな感じですかね。

A改.java
import java.util.Scanner;
class Main{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);

		//N、Sの受け取り
		int N = sc.nextInt();
		String S = sc.next();

		//末尾の文字を出力
		System.out.println(S.charAt(N-1));
	}
}

charAtで一文字だけ取り出せるので使ってみました。

B - Go Straight and Turn Right

問題文はこちら

シミュレーションをしました。
今の向きを表す変数を持っておいて、Rの度に+1して90度回転するようにしました。

B.java
import java.io.*;
//文字列を一文字ずつ区切って受け取る用
class subMain{
	public static String[] parStr(String someStr){
		String[] str = someStr.split("");
		return str;
	}
}
class Main{
	public static void main(String[] args)throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		//Nは必要無い
		String decoy = br.readLine();

		//Tの受け取り
		String[] str = subMain.parStr(br.readLine());

		//向きを表す変数
		int to = 0;

		//現在位置を表す変数
		int x = 0;
		int y = 0;

		//順に見ていく
		for(int i=0;i<str.length;i++){

			//Sの時はその方向に合わせて移動
			if(str[i].equals("S")){
				switch(to){
					case 0:
						x++;
						break;
					case 1:
						y--;
						break;
					case 2:
						x--;
						break;
					case 3:
						y++;
						break;

					//不必要だけど念のため
					default:
						break;
				}
			}

			//Rの時は方向転換
			else{
				to = (to+1) % 4;
			}
		}

		//出力
		System.out.println(x + " " + y);
	}
}

やっぱりちょっと長ったらしいので書き換えます。

B改.java
import java.util.Scanner;
class Main{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);

		//N、Tの受け取り
		int N = sc.nextInt();
		char[] T = sc.next().toCharArray();

		//向きと位置を表す変数
		int s=0,x=0,y=0;

		//順に見ていく
		for(int i=0;i<N;i++){

			//Sの時
			if(T[i]=='S'){
				if(s==0)x++;
				if(s==1)y--;
				if(s==2)x--;
				if(s==3)y++;
			}

			//Rの時
			else
				s = (s+1)%4;
		}

		//出力
		System.out.println(x+" "+y);
	}
}

TはString[]よりchar[]の方が扱いやすそうなのでこのように実装しました。

C - Yamanote Line Game

問題文はこちら

奇数個の整数をお互いに言うだけなので、当然ですが先攻の高橋君が勝ちます。
ですので、言ったか言ってないかを記録するboolean型配列を見ながら1から順に言っていけばACが取れます。

なお、System.outはデフォルトでオートフラッシュが有効ですので、フラッシュしてなくてTLEというのは気にする必要がありません。

C.java
import java.io.*;
class Main{
	public static void main(String[] args)throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		//Nの受け取り
		int N = Integer.parseInt(br.readLine());

		//使ったか管理する変数
		boolean[] ans = new boolean[2*N+1];

		//全部trueに
		for(int i=0;i<ans.length;i++){
			ans[i] = true;
		}

		//終了までずっと続ける
		while(true){

			//答える数値を保持する変数
			int temp = -1;
			for(int i=0;i<ans.length;i++){

				//まだ言ってない?
				if(ans[i]){
					temp = i;
					ans[i] = false;
					break;
				}
			}

			//無いとは思うけど、言ってないのが見つかってない時用
			if(temp==-1)
				System.exit(0);

			//答えの出力
			System.out.println(temp+1);

			//相手の答えの受け取り
			temp = Integer.parseInt(br.readLine());

			//oなら終了
			if(temp==0)
				System.exit(0);

			//記録
			ans[temp-1] = false;
		}
	}
}

特に書き直さなくて良いかなとは思いますが、書くならこんな感じでしょうか。

C改.java
import java.util.Scanner;
class Main{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);

		//Nの受け取り(後々楽なのでここで2倍+2する)
		int N = sc.nextInt()*2+2;

		//使ったかどうか管理する配列(1-indexedとして使う)
		boolean[] isUsed = new boolean[N];

		//1~2N+1まで見る
		for(int i=1;i<N;i++){
			//すでに相手が使ってる?
			if(isUsed[i])
				continue;

			//使ってないなら出力
			//なお、自分は今の数字以下を使用しないのでisUsed[i]をtrueにする必要は無い
			System.out.println(i);

			//相手の数字の受け取り
			int num = sc.nextInt();

			//0が返ってきたのでiより大きい数字は全てtrueであって
			//わざわざ終了する必要は無いが、念のため
			if(num==0)
				break;

			//相手が使った数字を記録
			isUsed[num] = true;
		}
	}
}

まぁこれで十分ですね。

D - Swap Hats

問題文はこちら

$10^{18}$回も帽子を入れ替えるとなるとシミュレーションでは当然終わりそうにありません。ではどう考えれば良いでしょうか。

一度初期状態から揃えたい順番に並べ替えてみましょう。そのときの回数を$K$回とすると、残りの回数は$10^{18}-K$となります。
ここで、残りの回数がどう消費されていくかを考えてみましょう。すると、いずれかの二人の帽子を入れ替え続けるという方法が浮かびます。この行為は最初揃っている状態から入れ替えて、また元の揃っている状態に戻るわけですから合計偶数回でないとちょうど揃った状態では終われません。
ということで、$10^{18}-K$が偶数、すなわち$K$が偶数であれば良いのです。

D.java
import java.io.*;

//空白区切りで文字列を受け取る用
class subMain{
	public static String[] parStrWithS(String someStr){
		String[] str = someStr.split(" ");
		return str;
	}
}
class Main{
	public static void main(String[] args)throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		//SとTの受け取り
		String[] start = subMain.parStrWithS(br.readLine());
		String[] finish = subMain.parStrWithS(br.readLine());

		//一個目が一致している?
		if(start[0].equals(finish[0])){

			//更に2個目が一致している=初期状態で全て揃ってるのでYes
			if(start[1].equals(finish[1])){
				System.out.println("Yes");
				System.exit(0);
			}

			//2個目が揃ってないなら1回、すなわち奇数回なのでNo
			else{
				System.out.println("No");
				System.exit(0);
			}
		}

		//1個目が揃ってない時
		else{
			//とりあえず揃えてみる
			if(start[1].equals(finish[0])){
				String temp = start[1];
				start[1] = start[0];
				start[0] = temp;
			}
			else{
				String temp = start[2];
				start[2] = start[0];
				start[0] = temp;
			}
		}

		//1個目を揃えた後に2個目が揃っている=1回で全部揃うのでNo
		if(start[1].equals(finish[1])){
			System.out.println("No");
			System.exit(0);
		}

		//2個目が揃ってない=2回で揃うのでYes
		System.out.println("Yes");
	}
}

ちょっと汚いので書き換えます。

D改.java
import java.util.Scanner;
class Main{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);

		//各文字の受け取り
		String S1 = sc.next();
		String S2 = sc.next();
		String S3 = sc.next();
		String T1 = sc.next();
		String T2 = sc.next();
		String T3 = sc.next();

		//揃っていない数を数える変数
		int count = 0;

		//それぞれ揃ってなければ加算
		if(!S1.equals(T1))count++;
		if(!S2.equals(T2))count++;
		if(!S3.equals(T3))count++;

		//二つが入れ替わっている=1回で揃うのでNo
		//他は0回か2回しかないのでYes
		System.out.println(count!=2?"Yes":"No");
	}
}

文字はどれも一文字で空白区切りだとわかっているのでchar[]で受け取っても良いかもしれません。

感想

A:簡単
B:まぁまぁ易しい
C:インタラクティブ問題だからといって身構える必要は無い問題だった
D:気付けば簡単
って感じでした。

普段のABCもこれくらい易しいと助かるんですが・・・。

0
0
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
0
0