AtCoder Beginner Contest 326 题解 A-D

目录

  • A - 2UP3DOWN
  • B - 326-like Numbers
  • C - Peak
  • D - ABC Puzzle

A - 2UP3DOWN

原题链接

题目描述
给定一个X代表你当前所在楼层,再给定一个Y代表你想要到达的楼层,但是你最多只能上两层楼或者下三层楼,问是否能够到达Y

思路:模拟

  • 比较大小。
public static void solve() throws IOException {
    int x = readInt(), y = readInt();
    if (x >= y) {
        printWriter.println(x - 3 <= y ? "Yes" : "No");
    } else {
        printWriter.println(x + 2 >= y ? "Yes" : "No");
    }
}

B - 326-like Numbers

原题链接

题目描述
给定一个整数N,求出一个大于等于N的满足百位数与十位数的乘积等于个位数的数。

思路:枚举

  • 不断枚举大于等于N的每个数,直至符合条件。
public static void solve() throws IOException{
    int n = readInt();
    while (true) {
        String s = String.valueOf(n);
        int a = s.charAt(s.length() - 1) - '0';
        int b = s.charAt(s.length() - 2) - '0';
        int c = s.charAt(s.length() - 3) - '0';
        if (b * c == a) {
            printWriter.println(n);
            break;
        }
        n++;
    }
}

C - Peak

原题链接

题目描述
一条无限长的数轴上只有N个点上有礼物,现在你可以在数轴上选择一段区间为M的线段,求出这条线段上最多可以有多少礼物。

思路:排序+二分

  • 排序后,枚举每个礼物,二分找到最近的小于 a r r [ i ] + m arr[i] + m arr[i]+m的礼物的所在位置 a r r [ j ] arr[j] arr[j],其中礼物数为 j − i + 1 j - i + 1 ji+1
public static void solve() throws IOException{
    int n = readInt(), m = readInt();
    int[] arr = utils.nextIntArray(n);
    Arrays.sort(arr, 1, n + 1);
    int max = 0;
    for (int i = 1; i <= n; i++) {
        int l = i - 1, r = n + 1;
        while (l + 1 < r) {
            int mid = l + r >> 1;
            if (arr[i] + m > arr[mid]) {
                l = mid;
            } else {
                r = mid;
            }
        }
        max = Math.max(max, l - i + 1);
    }
    printWriter.println(max);
}

D - ABC Puzzle

原题链接

题目描述
给定一个整数N和两个长度为N且仅包含字符ABC的字符串RC,请你构造出一个满足以下条件的 N × N N \times N N×N的二维矩阵。如果无法构造出输出No,否则输出Yes,并输出任意一个满足条件的矩阵。

  • 每一行和每一列仅包含一个A,一个B 和一个C
  • 每行最左边的字母组成的字符串和R相等。
  • 每列最上边的字母组成的字符串和C相等。

输入样例

5
ABCBC
ACAAB

输出样例

Yes
AC..B
.BA.C
C.BA.
BA.C.
..CBA

思路:dfs

  • 难点主要在于判断ABC的位置,使用三层循环枚举ABC每种位置的状态,每行ABC的排列情况最多只有 5 ∗ 4 ∗ 3 = 60 5 * 4 * 3 = 60 543=60种,同时通过R[u]进行优化枚举的情况,降低时间复杂度。
static int n;
static String s1, s2;
static char[][] map;
static boolean ok = false;

public static void solve() throws IOException {
    n = readInt();
    s1 = " " + readString(); s2 = " " + readString();
    map = new char[n + 1][n + 1];
    for (int i = 0; i <= n; i++) {
        Arrays.fill(map[i], '.');
    }
    dfs(1);
    if (!ok) {
        printWriter.println("No");
    }
}

public static void dfs(int u) {
    if (ok) return;
    if (u == n + 1) {
    	// 判断行是否满足条件
        for (int i = 1; i <= n; i++) {
            Set<Character> set = new HashSet<>();
            for (int j = 1; j <= n; j++) {
                if (map[i][j] != '.') {
                    if (set.contains(map[i][j])) return;// A,B,C只能出现一次
                    set.add(map[i][j]);
                }
            }
            if (set.size() <= 2) return;//  A,B,C没有各出现一次
            for (int j = 1; j <= n; j++) {
                if (map[i][j] != '.') {
                    if (s1.charAt(i) != map[i][j]) {// 该行首字母和 s1不对应
                        return;
                    }
                    break;
                }
            }
        }
        // 判断列是否满足条件
        for (int j = 1; j <= n; j++) {
            Set<Character> set = new HashSet<>();
            for (int i = 1; i <= n; i++) {
                if (map[i][j] != '.') {
                    if (set.contains(map[i][j])) return;// A,B,C只能出现一次
                    set.add(map[i][j]);
                }
            }
            if (set.size() <= 2) return;//  A,B,C没有各出现一次
            for (int i = 1; i <= n; i++) {
                if (map[i][j] != '.') {
                    if (s2.charAt(j) != map[i][j]) {// 该列首字母和 s2不对应
                        return;
                    }
                    break;
                }
            }
        }
        ok = true;
        printWriter.println("Yes");
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                printWriter.print(map[i][j]);
            }
            printWriter.println();
        }
        return;
    }

    // 每行ABC的排列情况最多只有 5 * 4 * 3 = 60种
    for (int i = 1; i <= n; i++) {// A的位置
        for (int j = 1; j <= n; j++) {// B的位置
            if (i == j) continue;
            for (int k = 1; k <= n; k++) {// C的位置
                if (i == k || j == k) continue;
                if (s1.charAt(u) == 'A') {
                	// 改行首字母为 A,那么 j和 k必须大于 i,即 B和 C必须在 A的后面 
                    if (!(i < j && i < k)) continue;
                } else if (s1.charAt(u) == 'B') {
                    if (!(j < i && j < k)) continue;
                } else if (s1.charAt(u) == 'C') {
                    if (!(k < i && k < j)) continue;
                }
                map[u][i] = 'A';
                map[u][j] = 'B';
                map[u][k] = 'C';
                dfs(u + 1);
                // 恢复原状
                map[u][i] = '.';
                map[u][j] = '.';
                map[u][k] = '.';
            }
        }
    }
}

你可能感兴趣的:(模拟,二分,深度优先搜索dfs,算法)