結果

問題 No.1405 ジグザグロボット
ユーザー CuriousFairy315CuriousFairy315
提出日時 2020-11-28 08:41:13
言語 Java21
(openjdk 21)
結果
RE  
実行時間 -
コード長 12,964 bytes
コンパイル時間 3,623 ms
コンパイル使用メモリ 93,512 KB
実行使用メモリ 58,940 KB
最終ジャッジ日時 2023-10-16 23:45:33
合計ジャッジ時間 14,765 ms
ジャッジサーバーID
(参考情報)
judge12 / judge14
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 63 ms
54,064 KB
testcase_01 AC 91 ms
54,688 KB
testcase_02 AC 54 ms
53,768 KB
testcase_03 AC 124 ms
58,684 KB
testcase_04 RE -
testcase_05 RE -
testcase_06 RE -
testcase_07 RE -
testcase_08 RE -
testcase_09 RE -
testcase_10 RE -
testcase_11 RE -
testcase_12 RE -
testcase_13 RE -
testcase_14 RE -
testcase_15 RE -
testcase_16 RE -
testcase_17 RE -
testcase_18 RE -
testcase_19 RE -
testcase_20 RE -
testcase_21 RE -
testcase_22 RE -
testcase_23 RE -
testcase_24 RE -
testcase_25 RE -
testcase_26 RE -
testcase_27 RE -
testcase_28 RE -
testcase_29 RE -
testcase_30 RE -
testcase_31 RE -
testcase_32 RE -
testcase_33 RE -
testcase_34 RE -
testcase_35 RE -
testcase_36 RE -
testcase_37 RE -
権限があれば一括ダウンロードができます

ソースコード

diff #

import java.awt.Point;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.NoSuchElementException;
import java.util.TreeSet;

public class Main {

	public static void main(final String[] args) {
		new Main();
	}

	public Main() {
		final InputChecker ic = new InputChecker(System.in);
		final java.io.PrintWriter out = new java.io.PrintWriter(System.out);
		solve(ic, out);
		out.flush();
	}

	public void solve(final InputChecker ic, final java.io.PrintWriter out) {
		final int N = ic.nextInt(1, 600);
		ic.nextChar(' ');
		final int X = ic.nextInt(0, N);
		ic.nextChar(' ');
		final int Y = ic.nextInt(0, N);
		ic.readNewLine();
		final CharSet query = new CharSet();
		query.add('L', 'S', 'R');
		final char[] S = ic.next(query).toCharArray();
		if (S.length != N) throw new AssertionError();
		ic.readNewLine();
		ic.checkEOF();

		Range[] range; // range[i]はy座標がiの時に左にl, 右にr動いて最終的に右にs動くことを示す
		int up = 0, right = 0;
		{
			final ArrayList<Range> list = new ArrayList<>();
			int l = 0, r = 0, s = 0, l2 = 0, i = 0;
			for (final char c : S) {
				if (c == 'S') {
					list.add(new Range(l, s, r, l2, i + 1));
					l = r = s = 0;
					l2 = i + 1;
					++ up;
				} else if (c == 'L') {
					-- s;
					l = Math.max(l, -s);
				} else if (c == 'R') {
					++ s;
					r = Math.max(r, s);
					++ right;
				} else throw new AssertionError();
				++ i;
			}
			list.add(new Range(l, s, r, l2, i + 1));
			range = list.toArray(new Range[0]);
		}
		if (up < Y || right < X) {
			out.println(-1);
			return;
		}
		final Range[][] merge = new Range[range.length][range.length + 1]; // merge[i][j]: y座標が[i, j)の区間を併合したときの合成区間
		for (int i = 0;i < merge.length;++ i) {
			final Range[] array = merge[i];
			array[i] = new Range(0, 0, 0, N, N);
			for (int j = i;j < merge.length;++ j)
				array[j + 1] = new Range(Math.max(array[j].l, range[j].l - array[j].s), array[j].s + range[j].s, Math.max(array[j].r, range[j].r + array[j].s), Math.min(array[j].l2, range[j].l2), range[j].r2);
		}
		final int[][] dp = new int[Y + 2][range.length + 1]; // dp[i][j]: i個の区間を選び、使用した区間がj個の時の右へ移動できる最大
		final int[][] restore = new int[Y + 2][range.length + 1]; // 復元
		for (int i = 1;i < dp.length;++ i) {
			final int[] last = dp[i - 1], now = dp[i];
			Arrays.fill(now, Integer.MIN_VALUE);
			final int[] res = restore[i];
			for (int j = 1;j < now.length;++ j)
				for (int k = j - 1;k >= 0;-- k)
					if (now[j] <= last[k] + merge[k][j].l + merge[k][j].s) { // 左はせき止めるため
						now[j] = last[k] + merge[k][j].l + merge[k][j].s;
						res[j] = k;
					}
		}

		int remain = dp[Y + 1][range.length] - X;
		if (remain < 0) {
			out.println(-1);
			return;
		}
		final ArrayDeque<Range> move = new ArrayDeque<>(); // 併合区間
		for (int i = Y + 1, j = range.length;i > 0;-- i) {
			final int next = restore[i][j];
			move.add(merge[next][j]);
			j = next;
		}
		final ArrayList<Point> ans = new ArrayList<>(); // 置いた岩の情報
		{
			int x = 0; // 現在の侵入座標
			for (int i = 0;i <= Y;++ i) {
				final Range m = move.pollLast();
				if (m.l + m.s <= remain) { // 移動しない
					ans.add(new Point(x - 1, i));
					ans.add(new Point(x + 1, i));
					remain -= m.l + m.s;
				} else if (remain == 0) {
					ans.add(new Point(x - 1, i));
					for (int j = 0;j < m.l + m.s;++ j) ans.add(new Point(x + j, i + 1));
					x += m.l + m.s;
				} else {
					ans.add(new Point(x - 1, i));
					for (int j = 0;j < m.l + m.s - remain;++ j) ans.add(new Point(x + j, i + 1));
					{
						int r = 0, s = 0;
						for (int j = m.l2;j < m.r2;++ j) {
							final char c = S[j];
							if (c == 'L') {
								-- s;
								if (s <= 0) {
									r = 0;
									s = 0;
								}
							} else if (c == 'R') {
								++ s;
								r = Math.max(r, s);
							}
						}
						r = Math.max(r, m.l + m.s);
						ans.add(new Point(x + r + 1 - remain, i));
					}
					x += m.l + m.s - remain;
					remain = 0;
				}
			}
			for (int i = 0;i <= N;++ i) ans.add(new Point(i, Y + 1));
		}

		{
			final TreeSet<Point> ans2 = new TreeSet<>((l, r) -> Integer.compare(l.x * 10000 + l.y, r.x * 10000 + r.y));
			final TreeSet<Integer> set = new TreeSet<>();
			for (final Point i : ans) set.add(i.x * 10000 + i.y);
			int x = 0, y = 0;
			for (final char c : S)
				if (c == 'S') {
					if (set.contains(x * 10000 + y + 1)) ans2.add(new Point(x, y + 1));
					else ++ y;
				} else if (c == 'L') {
					if (set.contains((x - 1) * 10000 + y)) ans2.add(new Point(x - 1, y));
					else -- x;
				} else if (c == 'R') if (set.contains((x + 1) * 10000 + y)) ans2.add(new Point(x + 1, y));
				else ++ x;
			if (x != X || y != Y) throw new AssertionError();
			out.println(ans2.size());
			for (final Point p : ans2)
				out.println(p.x + " " + p.y);
		}
	}

	class Range {
		final int l, s, r, l2, r2;
		Range(final int L, final int S, final int R, final int L2, final int R2) {
			l = L;
			s = S;
			r = R;
			l2 = L2;
			r2 = R2;
		}
		@Override
		public String toString() {
			return "[" + l2 + ", " + r2 + ") : " + "(" + l + "," + s + "," + r + ")";
		}
	}

	public static int exponent10(final int n, final int e) {
		return n * pow(10, e);
	}

	public static long exponent10L(final int n, final int e) {
		return n * pow(10L, e);
	}

	public static int pow(final int a, int b) {
		int ans = 1;
		for (int mul = a;b > 0;b >>= 1, mul *= mul) if ((b & 1) != 0) ans *= mul;
		return ans;
	}

	public static long pow(final long a, long b) {
		long ans = 1;
		for (long mul = a;b > 0;b >>= 1, mul *= mul) if ((b & 1) != 0) ans *= mul;
		return ans;
	}

	public static class CharSet {
		private final BitSet set = new BitSet(256);

		public void add(final char... c) {
			for (final char i : c) set.set(i);
		}

		public void add(final CharSet... s) {
			for (final CharSet i : s) set.or(i.set);
		}

		public boolean contains(final char... c) {
			for (final char i : c) if (!set.get(i)) return false;
			return true;
	 	}

		public boolean contains(final String s) {
			return contains(s.toCharArray());
	 	}

		private static final class Chars extends CharSet {
			public Chars(final char... c) {
				super.add(c);
			}
			public Chars(final CharSet... s) {
				super.add(s);
			}
			@Override
			public void add(final char... c) {
				throw new UnsupportedOperationException();
			}
			@Override
			public void add(final CharSet... s) {
				throw new UnsupportedOperationException();
			}
		}

		public static final CharSet NUMBER = new Chars('0','1','2','3','4','5','6','7','8','9');
		public static final CharSet LOWER = new Chars('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 final CharSet UPPER = new Chars('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 final CharSet ALPHABET = new Chars(LOWER, UPPER);

	}
	public static class InputChecker {
		private InputStream in;
		private final byte[] buffer = new byte[1024];
		private final byte[] undo = new byte[1024];
		private int undoSize = 0;
		private int read = 0;
		private int length = 0;

		public InputChecker(final InputStream in) {
			this.in = in;
		}

		public final void setInputStream(final InputStream in) {
			this.in = in;
		}

		public final void setInputStream(final File in) {
			try {
				this.in = new FileInputStream(in);
			} catch (final FileNotFoundException e) {
				e.printStackTrace();
			}
		}

		private boolean hasNextByte() {
			if (undoSize > 0) return true;
			if (read < length) return true;
			read = 0;
			try {
				length = in.read(buffer);
			} catch (final IOException e) {
				e.printStackTrace();
			}
			return length > 0;
		}

		private byte readByte() {
			if (hasNextByte()) return undoSize > 0 ? undo[--undoSize] : buffer[read++];
			throw new NoSuchElementException();
		}

		private void undo(final byte b) {
			undo[undoSize ++] = b;
		}

		private void undo(final char c) {
			if ((c & 0xFF80) == 0) {
				undo((byte)c);
				return;
			}
			undo((byte)(c & 0x3F | 0x80));
			if ((c & 0xF800) == 0) undo((byte)(c >> 6 & 0x1F | 0xC0));
			else {
				undo((byte)(c >> 6 & 0x3F | 0x80));
				undo((byte)(c >> 12 | 0xE0));
			}
		}

		public final boolean hasNext() {
			return hasNextByte();
		}

		public final char nextChar() {
			final byte b = readByte();
			if ((b & 0x80) == 0) return (char)b;
			if ((b & 0x20) == 0) return (char)((b & 0x1F) << 6 | readByte() & 0x3F);
			return (char)((b & 0xF) << 12 | (readByte() & 0x3F) << 6 | readByte() & 0x3F);
		}

		public final char nextChar(final char estimate) {
			final char c = nextChar();
			if (estimate == c) return estimate;
			undo(c);
			throw new AssertionError();
		}

		public final char nextChar(final CharSet estimate) {
			final char c = nextChar();
			if (estimate.contains(c)) return c;
			undo(c);
			throw new AssertionError();
		}

		public final void readNewLine() {
			char c = nextChar();
			if (c == '\r') {
				c = nextChar();
				if (c != '\n') undo(c);
				return;
			} else if (c == '\n') return;
			undo(c);
			throw new AssertionError();
		}

		public final void checkEOF() {
			if (hasNextByte()) throw new AssertionError();
		}

		public final String next(final CharSet contains) {
			final StringBuilder sb = new StringBuilder();
			try {
				do {
					final char c = nextChar();
					if (!contains.contains(c)) {
						undo(c);
						return sb.toString();
					}
					sb.append(c);
				} while(true);
			} catch (final NoSuchElementException e) {
				if (sb.length() <= 0) throw new AssertionError();
				return sb.toString();
			}
		}

		public final int nextInt() {
			byte b = readByte();
			int n = 0;
			if (b == '-') {
				if (!isNumber(b = readByte())) {
					undo(b);
					throw new NumberFormatException();
				}
				try {
					if (b == '0') {
						if (!isNumber(b = readByte())) {
							undo(b);
							return 0;
						}
						throw new NumberFormatException();
					}
					do n = Math.addExact(Math.multiplyExact(n, 10), '0' - b); while(isNumber(b = readByte()));
					undo(b);
				} catch (final NoSuchElementException e) {
				}
				return n;
			}
			if (!isNumber(b)) {
				undo(b);
				throw new NumberFormatException();
			}
			try {
				if (b == '0') {
					if (!isNumber(b = readByte())) {
						undo(b);
						return 0;
					}
					throw new NumberFormatException();
				}
				do n = Math.addExact(Math.multiplyExact(n, 10), b - '0'); while(isNumber(b = readByte()));
				undo(b);
			} catch (final NoSuchElementException e) {
			}
			return n;
		}

		public final int nextInt(final int min, final int max) {
			final int n = nextInt();
			if (min <= n && n <= max) return n;
			throw new NumberFormatException();
		}

		private static boolean isNumber(final byte c) {
			return '0' <= c && c <= '9';
		}

		public final long nextLong() {
			byte b = readByte();
			long n = 0;
			if (b == '-') {
				if (!isNumber(b = readByte())) {
					undo(b);
					throw new NumberFormatException();
				}
				try {
					if (b == '0') {
						if (!isNumber(b = readByte())) {
							undo(b);
							return 0;
						}
						throw new NumberFormatException();
					}
					do n = Math.addExact(Math.multiplyExact(n, 10), '0' - b); while(isNumber(b = readByte()));
					undo(b);
				} catch (final NoSuchElementException e) {
				}
				return n;
			}
			if (!isNumber(b)) {
				undo(b);
				throw new NumberFormatException();
			}
			try {
				if (b == '0') {
					if (!isNumber(b = readByte())) {
						undo(b);
						return 0;
					}
					throw new NumberFormatException();
				}
				do n = Math.addExact(Math.multiplyExact(n, 10), b - '0'); while(isNumber(b = readByte()));
				undo(b);
			} catch (final NoSuchElementException e) {
			}
			return n;
		}

		public final long nextLong(final long min, final long max) {
			final long n = nextLong();
			if (min <= n && n <= max) return n;
			throw new NumberFormatException();
		}

		public final double nextDouble() {
			final StringBuilder sb = new StringBuilder();
			byte b = readByte();
			if (b == '-') {
				sb.append(b);
				b = readByte();
			}
			if (b == '0') {
				sb.append(b);
				b = readByte();
			} else while(isNumber(b)) {
				sb.append(b);
				b = readByte();
			}
			if (b == '.') {
				sb.append(b);
				b = readByte();
				while(isNumber(b)) {
					sb.append(b);
					b = readByte();
				}
			}
			if (b == 'e' || b == 'E') {
				sb.append(b);
				b = readByte();
				if (b == '-' || b == '+') {
					sb.append(b);
					b = readByte();
				}
				while(isNumber(b)) {
					sb.append(b);
					b = readByte();
				}
			}
			undo(b);
			return Double.parseDouble(sb.toString());
		}
	}
}
0