返回目录
题目描述
有一个考古学家发现一个石碑,但是很可惜,发现时其已经断成多段,原地发现n个断口整齐的石碑碎片。为了破解石碑内容,考古学家希望有程序能帮忙计算复原后的石碑文字组合数,你能帮忙吗?
输入描述
第一行输入n,n表示石碑碎片的个数。
第二行依次输入石碑碎片上的文字内容s,共有n组。
输出描述
输出石碑文字的组合(按照升序排列),行末无多余空格。
示例:
输入 | 3 a b c |
---|---|
输出 | abc acb bac bca cab aba |
说明 | 无 |
解体思路
解决这个问题的方法是使用深度优先搜索(DFS)遍历所有可能的组合。以下是详细的思路:
- 首先,读取输入的石碑碎片个数
n
和石碑碎片上的文字内容s
。 - 将输入的石碑碎片内容存入一个列表
charArray
,并对其进行排序。排序的目的是为了在遍历过程中方便地跳过重复的组合。 定义一个深度优先搜索函数
dfs
,其中包含以下参数:charArray
:存储石碑碎片内容的列表。depth
:当前搜索的深度。path
:存储已经使用过的碎片。used
:记录每个碎片是否被使用过。result
:存储所有可能的组合。
- 在
dfs
函数中,首先检查当前搜索的深度是否等于石碑碎片的个数。如果是,则将当前组合加入结果列表result
。 - 遍历
charArray
中的每个碎片。对于每个碎片,检查它是否已经被使用过,以及它是否与前一个碎片相同且前一个碎片未被使用。如果满足这些条件,则跳过当前碎片。 - 将当前碎片添加到
path
中,并标记它为已使用。然后递归地搜索下一个碎片。 - 在递归返回后,执行回溯操作:将当前碎片从
path
中移除,并标记它为未使用。 - 调用
dfs
函数,开始搜索所有可能的组合。 - 最后,输出所有找到的组合。
这种方法可以有效地遍历所有可能的石碑文字组合,并通过跳过重复的组合来减少搜索空间。
Python算法源码
# 深度优先搜索函数
def dfs(char_array, depth, path, used, result):
# 如果碎片都已经被使用过,将当前组合加入结果中
if depth == len(char_array):
result.append(path[:])
return
for i in range(len(char_array)):
# 如果碎片已经被使用过,则跳过
if used[i]:
continue
# 如果当前碎片和前一个碎片相同,并且前一个碎片还没有被使用,则跳过
if i > 0 and char_array[i] == char_array[i - 1] and not used[i - 1]:
continue
path.append(char_array[i]) # 将当前碎片存入 path 中
used[i] = True # 标记当前碎片已被使用
dfs(char_array, depth + 1, path, used, result) # 递归搜索下一个碎片
path.pop() # 回溯,将当前碎片从 path 中移除
used[i] = False # 标记当前碎片未被使用
if __name__ == "__main__":
n = int(input())
char_array = input().split()
result = []
# 先对碎片进行排序
char_array.sort()
# path 中存储已经使用过的碎片
path = []
# 记录每个碎片是否被使用过
used = [False] * n
dfs(char_array, 0, path, used, result)
# 输出所有组合
for combination in result:
print(''.join(combination))
C算法源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_N 100
// 深度优先搜索函数
void dfs(char charArray[], int n, int depth, char path[], int used[], char result[MAX_N][MAX_N], int* resultCount) {
// 如果碎片都已经被使用过,将当前组合加入结果中
if (depth == n) {
strcpy(result[(*resultCount)++], path);
return;
}
for (int i = 0; i < n; i++) {
// 如果碎片已经被使用过,则跳过
if (used[i]) {
continue;
}
// 如果当前碎片和前一个碎片相同,并且前一个碎片还没有被使用,则跳过
if (i > 0 && charArray[i] == charArray[i - 1] && !used[i - 1]) {
continue;
}
path[depth] = charArray[i]; // 将当前碎片存入 path 中
used[i] = 1; // 标记当前碎片已被使用
dfs(charArray, n, depth + 1, path, used, result, resultCount); // 递归搜索下一个碎片
used[i] = 0; // 标记当前碎片未被使用
}
}
int main() {
int n;
scanf("%d", &n);
char charArray[MAX_N];
for (int i = 0; i < n; i++) {
scanf("%s", &charArray[i]);
}
char result[MAX_N][MAX_N];
int resultCount = 0;
// 先对碎片进行排序
qsort(charArray, n, sizeof(char), strcmp);
// path 中存储已经使用过的碎片
char path[MAX_N];
// 记录每个碎片是否被使用过
int used[MAX_N] = {0};
dfs(charArray, n, 0, path, used, result, &resultCount);
// 输出所有组合
for (int i = 0; i < resultCount; i++) {
printf("%s\n", result[i]);
}
return 0;
}
java算法源码
import java.util.*;
public class Main {
// 深度优先搜索函数
static void dfs(char[] charArray, int depth, StringBuilder path, boolean[] used, List<String> result) {
// 如果碎片都已经被使用过,将当前组合加入结果中
if (depth == charArray.length) {
result.add(path.toString());
return;
}
for (int i = 0; i < charArray.length; i++) {
// 如果碎片已经被使用过,则跳过
if (used[i]) {
continue;
}
// 如果当前碎片和前一个碎片相同,并且前一个碎片还没有被使用,则跳过
if (i > 0 && charArray[i] == charArray[i - 1] && !used[i - 1]) {
continue;
}
path.append(charArray[i]); // 将当前碎片存入 path 中
used[i] = true; // 标记当前碎片已被使用
dfs(charArray, depth + 1, path, used, result); // 递归搜索下一个碎片
path.deleteCharAt(path.length() - 1); // 回溯,将当前碎片从 path 中移除
used[i] = false; // 标记当前碎片未被使用
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
scanner.nextLine(); // Consume newline
char[] charArray = scanner.nextLine().replaceAll("\\s", "").toCharArray();
List<String> result = new ArrayList<>();
// 先对碎片进行排序
Arrays.sort(charArray);
// path 中存储已经使用过的碎片
StringBuilder path = new StringBuilder();
// 记录每个碎片是否被使用过
boolean[] used = new boolean[n];
dfs(charArray, 0, path, used, result);
// 输出所有组合
for (String res : result) {
System.out.println(res);
}
}
}
2 条评论
[...]2024 C卷 100分序号题目知 识 点难易程度1密码输入检测数据结构/栈☆☆☆2分配土地几何问题☆☆☆3找座位逻辑分析☆☆☆4智能成绩表动态条件分析☆☆☆5内存冷热标记多条件排序☆☆☆6螺旋数字矩阵逻辑分析☆☆☆7围棋的气逻辑分析☆☆☆8分割平衡字符串逻辑分析☆☆☆9机器人搬砖二分法☆☆☆10转盘寿司数据结构/栈/单调栈☆☆☆11小明找位置二分法☆☆☆12提取字符串的最长合法简单数学表达式双指[...]
[...]2024 C卷 100分序号题目知 识 点难易程度1密码输入检测数据结构/栈☆☆☆2分配土地几何问题☆☆☆3找座位逻辑分析☆☆☆4智能成绩表动态条件分析☆☆☆5内存冷热标记多条件排序☆☆☆6螺旋数字矩阵逻辑分析☆☆☆7围棋的气逻辑分析☆☆☆8分割平衡字符串逻辑分析☆☆☆9机器人搬砖二分法☆☆☆10转盘寿司数据结构/栈/单调栈☆☆☆11小明找位置二分法☆☆☆12提取字符串的最长合法简单数学表达式双指[...]