Seven Puzzle(AOJ No.0121), Summer of Phyonkichi(AOJ No.0122), Speed Skating Badge Test(AOJ No.0123), League Match Score Sheet(AOJ No.0124), Day Count(AOJ No.0125), Puzzle(AOJ No.0126), Pocket Pager Input(AOJ No.0127), Abacus(AOJ No.0128), Hide-and-Seek Su
Seven Puzzle(AOJ No.0121)
のパズル、0〜7のパネルが与えられて、
0のパネルを上下左右のどれかのパネルと交換して、
0 | 1 | 2 | 3 |
4 | 5 | 6 | 7 |
の状態にするゲーム。
与えられた状態から、上の最終状態にするまでの最小の交換回数を求める。
ただし、ゲームクリア可能な初期状態しか与えられないものとする。
コード
ルールを勘違いしてて、無駄に時間がかかった。状態は文字列で持ってる。
久しぶりのコンパイルエラー。提出するとき、クラス名とコンストラクタの名前かえるの忘れてた。
import java.util.*; public class aoj0121 { static final Scanner stdin = new Scanner(System.in); static final String INISTR = "01234567"; static final int N = INISTR.length(); static final HashMap<String, Integer> map = new HashMap<String, Integer>(); static final int[] offset = {-1, 1, +4, -4}; public static void main(String[] args) { BFS(); while(stdin.hasNext()){ StringBuilder line = new StringBuilder(N); for(int i = 0; i < N; ++i) line.append(stdin.nextInt()); System.out.println(map.get(line.toString())); } } static String swap(String str, int i, int j){ StringBuilder chars = new StringBuilder(str); char c = chars.charAt(i); chars.setCharAt(i, chars.charAt(j)); chars.setCharAt(j, c); return chars.toString(); } static class Node{ String state; int count; int pos0; Node(String state, int count, int pos0){this.state = state; this.count = count; this.pos0 = pos0;} } static void BFS(){ Queue<Node> q = new LinkedList<Node>(); q.add(new Node(INISTR, 0, 0)); map.put(INISTR, 0); while(!q.isEmpty()){ Node n = q.poll(); for(int d: offset){ int j = n.pos0 + d; if(j >=0 && j < N && !(n.pos0 == 3 && d == 1 || n.pos0 == 4 && d == -1) ){ String next = swap(n.state, n.pos0, j); if(!map.containsKey(next)){ map.put(next, n.count + 1); q.add(new Node(next, n.count + 1, j)); } } } } } }
Summer of Phyonkichi(AOJ No.0122)
のマスにn個のスプリンクラーがある。
カエルの位置を○とすると、このカエルは、次に■の位置のどれかにジャンプする。
□■■■□
■□□□■
■□○□■
■□□□■
□■■■□
また、スプリンクラーはカエルがi回ジャンプしたとき周囲8近傍に散水し(も含む)、次にカエルがジャンプするタイミングで散水をやめる。
カエルの初期位置(x,y)とスプリンクラーの位置が与えられたとき、
カエルがすべてのスプリンクラーの水を浴びられるかを答える。
コード
import java.util.*; public class aoj0122 { static final Scanner stdin = new Scanner(System.in); static final int[] offx = {0, 1, 2, 2, 2, 1, 0, -1, -2, -2, -2, -1}; static final int[] offy = {-2, -2, -1, 0, 1, 2, 2, 2, 1, 0, -1, -2}; static class State implements Comparable<State>{ int x, y, time; State(int x, int y, int time){this.x = x; this.y = y; this.time = time; } public int compareTo(State o) { return this.x < o.x ? -1 : this.x > o.x ? 1 : this.y < o.y ? -1 : this.y > o.y ? 1 : this.time < o.time ? -1 : this.time > o.time ? 1 : 0; } } static final int N = offx.length; public static void main(String[] args) { while(true){ int x = stdin.nextInt(), y = stdin.nextInt(); if(x == 0 && y == 0) break; int n = stdin.nextInt(); int[] sx = new int[n], sy = new int[n]; for(int i = 0; i < n; ++i){ sx[i] = stdin.nextInt(); sy[i] = stdin.nextInt(); } System.out.println(BFS(x, y, n, sx, sy) ? "OK" : "NA"); } } static boolean BFS(int x, int y, int n, int[] sx, int[]sy){ Queue<State> q = new LinkedList<State>(); State s = new State(x, y, -1); q.add(s); TreeSet<State> map = new TreeSet<State>(); map.add(s); while(!q.isEmpty()){ s = q.poll(); if(s.time == n-1) return true; for(int i = 0; i < N; ++i){ int nx = s.x + offx[i], ny = s.y + offy[i]; if(check(nx, ny, sx[s.time+1], sy[s.time+1])){ State ns = new State(nx, ny, s.time + 1); if(!map.contains(ns)){ q.add(new State(nx, ny, ns.time)); map.add(ns); } } } } return false; } static boolean check(int x, int y, int sx, int sy){ return 0 <= x && 0 <= y && x < 10 && y < 10 && sx-1 <= x && x <= sx+1 && sy-1 <= y && y <= sy+1; } }
Speed Skating Badge Test(AOJ No.0123)
500M, 1000Mのタイムが与えられて、以下の表でランク付けする。
500M, 1000Mどちらのタイムも下の表のある級のタイム未満だったら、その級が認められる。
E級以下ならNAと答える。
男子 | 500M | 1000M |
AAA級 | 35秒50 | 1分11秒00 |
AA級 | 37秒50 | 1分17秒00 |
A級 | 40秒00 | 1分23秒00 |
B級 | 43秒00 | 1分29秒00 |
C級 | 50秒00 | 1分45秒00 |
D級 | 55秒00 | 1分56秒00 |
E級 | 1分10秒00 | 2分28秒00 |
コード
思ったより短く書けた
import java.util.*; public class aoj0123 { static final Scanner stdin = new Scanner(System.in); static String[] rank = {"AAA", "AA", "A", "B", "C", "D", "E", "NA"}; static double[][] time = {{35.5, 71.0}, {37.5, 77.0}, {40.0, 83.0}, {43.0, 89.0}, {50.0, 105.0}, {55.0, 116.0}, {70.0, 148.0}}; public static void main(String[] args) { while(stdin.hasNext()){ double a = stdin.nextDouble(), b = stdin.nextDouble(); int i; for(i = 0; i < time.length; ++i) if(a < time[i][0] && b < time[i][1]) break; System.out.println(rank[i]); } } }
League Match Score Sheet(AOJ No.0124)
勝ち3点、負け0点、引き分け1点で得点計算する。
チーム名と、価値、負け、引き分けの数が与えられて、それを集計し、得点順にソートして、
チーム名と得点を出力する。
同じ得点のチームが存在する場合は、入力順にする。
コード
Arrays.sortが安定ソートだと初めて知った。
チーム数をstdin.nextInt()で読み込んで、stdin.nextLine()で改行を空読みして、レコードをstdin.nextLine().split("")で読み込んだら、
これが原因か知らんが、なんかruntime errorになった。
いつもはこれでAcceptしてたんだけど、最後の改行の空読みがだめだったのかな(最後の0の後に改行がなくEOFがあった???)?
import java.util.*; public class aoj0124 { static final Scanner stdin = new Scanner(System.in); static class Record{ String name; int point; Record(String name, int point){ this.name = name; this.point = point; } } public static void main(String[] args) { boolean flag = false; while(true){ int n = stdin.nextInt(); if(n == 0) break; if(flag) System.out.println(""); flag = true; Record[] a = new Record[n]; for(int i = 0; i < n; ++i) a[i] = new Record(stdin.next(), 3*stdin.nextInt() + 0*stdin.nextInt() + stdin.nextInt()); Arrays.sort(a, new Comparator<Record>(){ public int compare(Record o1, Record o2){ return o1.point > o2.point ? -1 : o1.point == o2.point ? 0 : 1; } }); for(Record r: a) System.out.println(r.name + "," + r.point); } } }
Day Count(AOJ No.0125)
ymd形式で二つの日付が与えられ、その日数差を答える。
コード
Julian day求めて引き算するだけです。
import java.util.*; public class aoj0125 { static final Scanner stdin = new Scanner(System.in); public static void main(String[] args) { while(true){ int y1 = stdin.nextInt(), m1 = stdin.nextInt(), d1 = stdin.nextInt(); int y2 = stdin.nextInt(), m2 = stdin.nextInt(), d2 = stdin.nextInt(); if(y1 == -1) break; System.out.println(GregToJD(y2, m2, d2, true) - GregToJD(y1, m1, d1, true)); } } public static final int GregToJD(int y, int m, int d, boolean modflag){ // Ver. 2 int a = (14-m)/12; y = y + 4800 - a; m = m + 12*a -3; return d + (153*m+2)/5 + 365 * y + y/4 - y/100 + y/400 - 32045 - (modflag ? 2400001 : 0); } }
Puzzle(AOJ No.0126)
ナンプレのテーブルが与えられて、ルール違反している部分に印を付ける。
コード
投げやりすぎる
import java.util.*; public class aoj0126 { static final Scanner stdin = new Scanner(System.in); static final boolean[][] flag = new boolean[9][9]; static final int[][] p = new int[9][9]; static final int[] freq = new int[10]; static void checkRow(int i){ Arrays.fill(freq, 0); for(int x: p[i]) freq[x]++; for(int j = 0; j < 9; ++j) if(freq[p[i][j]] > 1) flag[i][j] = false; } static void checkCol(int j){ Arrays.fill(freq, 0); for(int i = 0; i < 9; ++i) freq[p[i][j]]++; for(int i = 0; i < 9; ++i) if(freq[p[i][j]] > 1) flag[i][j] = false; } static void checkSq(int i, int j){ Arrays.fill(freq, 0); for(int I = i; I < i + 3; ++I) for(int J = j; J < j + 3; ++J) freq[p[I][J]]++; for(int I = i; I < i + 3; ++I) for(int J = j; J < j + 3; ++J) if(freq[p[I][J]] > 1) flag[I][J] = false; } public static void main(String[] args) { int n = stdin.nextInt(); while(true){ for(int i = 0; i < 9; ++i){ for(int j = 0; j < 9; ++j) p[i][j] = stdin.nextInt(); Arrays.fill(flag[i], true); } for(int i = 0; i < 9; ++i){ checkCol(i); checkRow(i); } for(int i = 0; i < 9; i+=3) for(int j = 0; j < 9; j+=3) checkSq(i,j); for(int i = 0; i < 9; i++){ for(int j = 0; j < 9; j++) System.out.print((flag[i][j] ? " " : "*") + p[i][j]); System.out.println(); } if(--n != 0) System.out.println(); else break; } } }
Pocket Pager Input(AOJ No.0127)
ポケベルうちによる入力系列が与えられて、下の表に従って、デコードする。
デコードが失敗するときは、NAと答える。
1 | 2 | 3 | 4 | 5 | 6 | |
1 | a | f | k | p | u | z |
2 | b | g | l | p | v | . |
3 | c | h | m | r | w | ? |
4 | d | i | n | s | x | ! |
5 | e | j | o | t | y |
コード
めんどいんでtry catchでいいや
import java.util.*; public class aoj0127 { static final Scanner stdin = new Scanner(System.in); static char[][] map = { {'a', 'b', 'c', 'd', 'e'}, {'f', 'g', 'h', 'i', 'j'}, {'k', 'l', 'm', 'n', 'o'}, {'p', 'q', 'r', 's', 't'}, {'u', 'v', 'w', 'x', 'y'}, {'z', '.', '?', '!', ' '}}; public static void main(String[] args) { while(stdin.hasNext()){ char[] line = stdin.nextLine().toCharArray(); StringBuilder ans = new StringBuilder(); try{ for(int i = 0; i < line.length; i+=2) ans.append(map[line[i]-'1'][line[i+1]-'1']); }catch(Exception e){ ans = new StringBuilder("NA"); }finally{ System.out.println(ans.toString()); } } } }
コード
import java.util.*; public class aoj0128 { static final Scanner stdin = new Scanner(System.in); static final String[] abacus = {"* = ****", "* =* ***", "* =** **", "* =*** *", "* =**** ", " *= ****", " *=* ***", " *=** **", " *=*** *", " *=**** " }; public static void main(String[] args) { boolean flag = false; while(stdin.hasNext()){ if(flag) System.out.println(); flag = true; String line = String.format("%05d", stdin.nextInt()); for(int i = 0; i < 8; ++i){ for(int j = 0; j < 5; ++j) System.out.print(abacus[line.charAt(j)-'0'].charAt(i)); System.out.println(); } } } }
Hide-and-Seek Supporting System(AOJ No.0129)
AとBがかくれんぼをしている。個の円形の障害物の中心座標と半径と、A,Bの座標が与えられる。
BがAを視認できるかを答える。
障害物の後ろにいる場合は、視認できない(境界にいる場合も含む)。
また、どちらも同じ障害物の中にいる場合、ほかの障害物に遮られていなければ、視認できる。
アルゴリズム
まず、同じ円内にA, Bがいるかを求める。いなければ視認不可。
一つ以上、同じ円内にA, Bがいれば、
それらの円を除く他の円と線分ABの交差判定をする。
一つでも交差していれば、視認不可、
交差していなければ、視認可
コード
ライブラリをコピペしているから無駄に長い。
やりかたももっといいのがあると思うが、こういう問題を正解できるとうれしいですね。
import java.awt.geom.Point2D; import java.util.*; public class aoj0129 { static final Scanner stdin = new Scanner(System.in); public static void main(String[] args) { while(true){ int n = stdin.nextInt(); if(n == 0) break; boolean[] A = new boolean[n], B = new boolean[n]; Circle[] c = new Circle[n]; for(int i = 0; i < n; ++i) c[i] = new Circle(stdin.nextDouble(), stdin.nextDouble(), stdin.nextDouble()); int m = stdin.nextInt(); for(int i = 0; i < m; ++i){ boolean flag = true; Arrays.fill(A, false); Arrays.fill(B, false); Line s = new Line(stdin.nextDouble(), stdin.nextDouble(), stdin.nextDouble(), stdin.nextDouble()); for(int j = 0; j < n; ++j){ if(s.start.intersectsPC(c[j])) A[j] = true; if(s.end.intersectsPC(c[j])) B[j] = true; if(A[j] == B[j]) flag = false; } if(flag){ System.out.println("Safe"); continue; } flag = false; for(int j = 0; j < n; ++j){ if(A[j] && B[j]) continue; if(s.intersectsSC(c[j])){ flag = true; break; } } System.out.println(flag ? "Safe" : "Danger"); } } } public static final double EPS = 1e-10; public static boolean equal(double a, double b){ return Math.abs(a-b) < EPS; } // a == b public static boolean less(double a, double b){ return a - b < -EPS; } // a < b public static boolean leq(double a, double b){ return a - b < EPS; } // a <= b public static boolean greater(double a, double b){ return less(b,a); } // a > b public static boolean geq(double a, double b){ return leq(b,a); } // a >= b @SuppressWarnings("serial") public static class Point extends Point2D.Double { public Point(double x, double y){ super(x,y); } public final double norm(){ return Math.sqrt( normsq() ); } public final double normsq(){ return x*x + y*y; } public final Point add(Point p){ return new Point( x + p.x, y + p.y ); } public final Point sub(Point p){ return new Point( x - p.x, y - p.y ); } public final Point mul(double k){ return new Point( k*x, k*y ); } public final double dot(Point p){ return x * p.x + y * p.y; } public final Point projection(Line l){ Point a = l.dirV(); Point b = this.sub(l.start); return l.start.add(a.mul(a.dot(b)/a.normsq())); } public final boolean intersectsPC(Circle c){ return leq(distanceSq(c.o), c.r*c.r); } public final double distancePS(Line s){ Point proj = projection(s); return proj.intersectsPS(s) ? distance(proj) : Math.min(distance(s.start), distance(s.end)); } public final boolean intersectsPS(Line s) { return equal(s.start.distance(this) + this.distance(s.end), s.end.distance(s.start)); //三角不等式で等号が成り立つとき } } //class Point public static class Line{ private final Point start, end; public Line(double sx, double sy, double ex, double ey){ start = new Point(sx,sy); end = new Point(ex,ey); } public Point dirV() { return end.sub(start); } //directional vector public final double distanceSP(Point p){ return p.distancePS(this); } public final boolean intersectsSC(Circle c) { return geq(c.r, distanceSP(c.o)); } } //class Line public static class Circle{ public final Point o; public double r; public Circle(double x, double y, double r){ this.o = new Point(x,y); this.r = r; } } }
Train(AOJ No.0130)
列車に小文字アルファベットの名前がついていて、26両以下の編成になっている。
その中で、巡回していて、どの方向に巡回しているかと、車両名を表す系列が与えられる。
これを解読して、車両の並びを答える。
車両名はだぶっていない。
コード
泥臭い実装
import java.util.*; public class aoj0130 { static final Scanner stdin = new Scanner(System.in); public static void main(String[] args) { int n = stdin.nextInt(); while(n-->0){ char[] line = stdin.next().toCharArray(); StringBuilder ans = new StringBuilder(); boolean flag = true; int p = -1; for(int i = 0; i < line.length; ++i){ switch(line[i]){ case '-': break; case '<': flag = true; p--; break; case '>': flag = false; p++; break; default: if(p < 0 || ans.length() <= p){ if(flag){ ans.insert(0,line[i]); p++; } else{ ans.append(line[i]); } } } } System.out.println(ans.toString()); } } }