目录
- [A - 2UP3DOWN](#A - 2UP3DOWN)
- [B - 326-like Numbers](#B - 326-like Numbers)
- [C - Peak](#C - Peak)
- [D - ABC Puzzle](#D - ABC Puzzle)
A - 2UP3DOWN
题目描述
给定一个
X
代表你当前所在楼层,再给定一个Y
代表你想要到达的楼层,但是你最多只能上两层楼或者下三层楼 ,问是否能够到达Y
。思路:模拟
- 比较大小。
java
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
的每个数,直至符合条件。
java
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 j−i+1。
java
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
的字符串R
和C
,请你构造出一个满足以下条件的 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 5∗4∗3=60种,同时通过R[u]
进行优化枚举的情况,降低时间复杂度。
java
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] = '.';
}
}
}
}