C/C++编程(1~8级)全部真题・点这里
一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。 给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
时间限制:1000
内存限制:65536
输入
第一行是两个整数,R和C,代表迷宫的长和宽。(1<= R,C <= 40) 接下来是R行,每行C个字符,代表整个迷宫。 空地格子用’.‘表示,有障碍物的格子用’#‘表示。 迷宫左上角和右下角都是’.'。
输出
输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。计算步数要包括起点和终点。
样例输入
5 5
…###
#…
#.#.#
#.#.#
#.#…
样例输出
9
以下是一个使用C语言编写的解决方案:
#include
#include
#include
#define MAX_SIZE 40
// 迷宫结构体定义
typedef struct {
int row;
int col;
} Point;
// 队列结构体定义
typedef struct {
Point queue[MAX_SIZE * MAX_SIZE];
int front;
int rear;
} Queue;
// 初始化队列
void initQueue(Queue *q) {
q->front = 0;
q->rear = 0;
}
// 判断队列是否为空
bool isEmpty(Queue *q) {
return q->front == q->rear;
}
// 入队操作
void enqueue(Queue *q, Point p) {
q->queue[q->rear++] = p;
}
// 出队操作
Point dequeue(Queue *q) {
return q->queue[q->front++];
}
// 判断坐标是否有效
bool isValid(int row, int col, int R, int C) {
return row >= 0 && row < R && col >= 0 && col < C;
}
// BFS搜索迷宫
int bfs(char maze[MAX_SIZE][MAX_SIZE], int R, int C) {
int dr[] = {-1, 1, 0, 0}; // 上下左右四个方向的行偏移量
int dc[] = {0, 0, -1, 1}; // 上下左右四个方向的列偏移量
Queue queue;
initQueue(&queue); // 初始化队列
Point start = {0, 0}; // 起点坐标
enqueue(&queue, start);
int steps[MAX_SIZE][MAX_SIZE]; // 记录每个格子的步数
int i, j;
for (i = 0; i < R; i++) {
for (j = 0; j < C; j++) {
steps[i][j] = -1; // 初始化为-1表示未访问过
}
}
steps[0][0] = 0; // 起点步数为0
while (!isEmpty(&queue)) {
Point curr = dequeue(&queue);
if (curr.row == R - 1 && curr.col == C - 1) // 到达终点
return steps[curr.row][curr.col];
for (i = 0; i < 4; i++) {
int newRow = curr.row + dr[i];
int newCol = curr.col + dc[i];
if (isValid(newRow, newCol, R, C) && maze[newRow][newCol] == '.' && steps[newRow][newCol] == -1) {
Point next = {newRow, newCol};
enqueue(&queue, next);
steps[newRow][newCol] = steps[curr.row][curr.col] + 1;
}
}
}
return -1; // 无法到达终点
}
int main() {
int R, C;
scanf("%d %d", &R, &C); // 读取迷宫的行数和列数
char maze[MAX_SIZE][MAX_SIZE];
int i, j;
for (i = 0; i < R; i++) {
scanf("%s", maze[i]); // 读取迷宫的每一行
}
int minSteps = bfs(maze, R, C); // 使用BFS搜索迷宫
printf("%d\n", minSteps);
return 0;
}
该程序使用广度优先搜索(BFS)算法来解决迷宫问题。首先定义了结构体Point
,用来表示迷宫中的坐标。然后定义了队列结构体Queue
,包含一个存储坐标的数组和队头、队尾指针。
程序中实现了以下几个函数:
initQueue
:初始化队列。
isEmpty
:判断队列是否为空。
enqueue
:入队操作,将坐标加入队列。
dequeue
:出队操作,将队头的坐标移出队列并返回。
isValid
:判断坐标是否在有效范围内。
bfs
:使用BFS搜索迷宫,返回从起点到终点的最少步数。
在主函数中,首先读取迷宫的行数和列数,然后使用一个二维字符数组maze
来存储迷宫的状态。接下来调用bfs
函数进行广度优先搜索,得到从起点到终点的最少步数,并将结果输出。
注意,这里的迷宫大小有限制,最大为40行40列,超过这个大小可能导致程序运行时间过长或内存溢出。
给定一棵二叉树的前序遍历和中序遍历的结果,求其后序遍历。
时间限制:1000
内存限制:65536
输入
输入可能有多组,以EOF结束。 每组输入包含两个字符串,分别为树的前序遍历和中序遍历。每个字符串中只包含大写字母且互不重复。
输出
对于每组输入,用一行来输出它后序遍历结果。
样例输入
DBACEGF ABCDEFG
BCAD CBAD
样例输出
ACBFGED
CDAB
样例输入
DBACEGF ABCDEFG
BCAD CBAD
样例输出
ACBFGED
CDAB
以下是一个使用C语言编写的解决方案:
#include
#include
#include
typedef struct TreeNode {
char val;
struct TreeNode *left;
struct TreeNode *right;
} TreeNode;
// 根据前序遍历和中序遍历构建二叉树
TreeNode *buildTree(char *preorder, char *inorder, int preStart, int preEnd, int inStart, int inEnd) {
if (preStart > preEnd || inStart > inEnd)
return NULL;
TreeNode *root = (TreeNode *)malloc(sizeof(TreeNode));
root->val = preorder[preStart];
root->left = NULL;
root->right = NULL;
int rootIndex;
for (int i = inStart; i <= inEnd; i++) {
if (inorder[i] == root->val) {
rootIndex = i;
break;
}
}
int leftSize = rootIndex - inStart;
int rightSize = inEnd - rootIndex;
root->left = buildTree(preorder, inorder, preStart + 1, preStart + leftSize, inStart, rootIndex - 1);
root->right = buildTree(preorder, inorder, preEnd - rightSize + 1, preEnd, rootIndex + 1, inEnd);
return root;
}
// 后序遍历二叉树
void postorderTraversal(TreeNode *root) {
if (root == NULL)
return;
postorderTraversal(root->left);
postorderTraversal(root->right);
printf("%c", root->val);
}
int main() {
char preorder[100];
char inorder[100];
while (scanf("%s %s", preorder, inorder) != EOF) {
int preLen = strlen(preorder);
int inLen = strlen(inorder);
TreeNode *root = buildTree(preorder, inorder, 0, preLen - 1, 0, inLen - 1);
postorderTraversal(root);
printf("\n");
free(root);
}
return 0;
}
该程序使用递归的方式构建二叉树,并进行后序遍历。
首先定义了二叉树的结构体TreeNode
,包含一个字符值val
,以及左子树和右子树的指针。
然后定义了两个函数:
buildTree
:根据前序遍历和中序遍历构建二叉树。该函数接受前序遍历字符串、中序遍历字符串以及遍历范围的起始和结束索引。根据前序遍历的第一个字符确定根节点,然后在中序遍历中找到根节点的位置,将中序遍历分为左子树和右子树部分。递归构建左子树和右子树,并将它们连接到根节点的左右指针上。
postorderTraversal
:后序遍历二叉树。该函数接受一个二叉树的根节点指针,先递归遍历左子树,然后递归遍历右子树,最后输出当前节点的值。
在主函数中,首先读取前序遍历和中序遍历的字符串,然后根据这两个字符串构建二叉树。接着调用postorderTraversal
函数进行后序遍历,输出结果。
注意,该程序假设输入的前序遍历和中序遍历是合法的,并且前序遍历和中序遍历的长度相等。如果输入不符合这些条件,程序可能会出错。另外,为了简化问题,该程序没有处理内存释放的情况,实际使用时应注意释放二叉树的内存。
小明有很多猪,他喜欢玩叠猪游戏,就是将猪一头头叠起来。猪叠上去后,还可以把顶上的猪拿下来。小明知道每头猪的重量,而且他还随时想知道叠在那里的猪最轻的是多少斤。
时间限制:1000
内存限制:65536
输入
有三种输入1)push n n是整数(0<=0 <=20000),表示叠上一头重量是n斤的新猪 2)pop 表示将猪堆顶的猪赶走。如果猪堆没猪,就啥也不干 3)min 表示问现在猪堆里最轻的猪多重。如果猪堆没猪,就啥也不干 输入总数不超过100000条
输出
对每个min输入,输出答案。如果猪堆没猪,就啥也不干
样例输入
pop
min
push 5
push 2
push 3
min
push 4
min
样例输出
2
2
以下是一个使用C语言编写的解决方案:
#include
#include
#include
typedef struct Pig {
int weight;
struct Pig *next;
} Pig;
typedef struct {
Pig *top;
} PigStack;
// 初始化猪堆
void initPigStack(PigStack *stack) {
stack->top = NULL;
}
// 将一头重量为weight的猪叠入猪堆
void pushPig(PigStack *stack, int weight) {
Pig *newPig = (Pig *)malloc(sizeof(Pig));
newPig->weight = weight;
newPig->next = stack->top;
stack->top = newPig;
}
// 将猪堆顶部的猪赶走
void popPig(PigStack *stack) {
if (stack->top == NULL)
return;
Pig *temp = stack->top;
stack->top = stack->top->next;
free(temp);
}
// 查询猪堆中最轻的猪的重量
int getMinWeight(PigStack *stack) {
if (stack->top == NULL)
return -1;
int minWeight = stack->top->weight;
Pig *current = stack->top->next;
while (current != NULL) {
if (current->weight < minWeight)
minWeight = current->weight;
current = current->next;
}
return minWeight;
}
int main() {
PigStack stack;
initPigStack(&stack);
char command[10];
int weight;
while (scanf("%s", command) != EOF) {
if (strcmp(command, "push") == 0) {
scanf("%d", &weight);
pushPig(&stack, weight);
} else if (strcmp(command, "pop") == 0) {
popPig(&stack);
} else if (strcmp(command, "min") == 0) {
int minWeight = getMinWeight(&stack);
if (minWeight != -1)
printf("%d\n", minWeight);
}
}
// 释放猪堆中剩余的猪的内存
Pig *current = stack.top;
while (current != NULL) {
Pig *temp = current;
current = current->next;
free(temp);
}
return 0;
}
该程序使用堆栈(栈)的数据结构来实现猪堆的操作。
首先定义了猪的结构体Pig
,包含一个整数值weight
表示猪的重量,以及一个指向下一头猪的指针next
。
然后定义了猪堆的结构体PigStack
,包含一个指向猪堆顶部的指针top
。
接下来定义了几个操作函数:
initPigStack
:初始化猪堆,将顶部指针置为空。
pushPig
:将一头重量为weight
的猪叠入猪堆。创建一个新的猪节点,将其重量设置为weight
,然后将它插入到猪堆的顶部。
popPig
:将猪堆顶部的猪赶走。如果猪堆为空,不做任何操作。否则,将顶部猪节点从堆栈中移除,并释放其内存。
getMinWeight
:查询猪堆中最轻的猪的重量。如果猪堆为空,返回-1。否则,遍历猪堆中的所有猪节点,找到最轻的猪的重量。
在主函数中,首先初始化猪堆。然后根据输入的命令执行相应的操作。如果命令是push
,则读取一个整数作为猪的重量,并将该猪叠入猪堆。如果命令是pop
,则将猪堆顶部的猪赶走。如果命令是min
,则查询猪堆中最轻的猪的重量并输出。
最后,在程序结束前,释放猪堆中剩余猪节点的内存。
注意,该程序假设输入的命令是合法的,并且不会超出内存限制。另外,为了简化问题,该程序没有处理输入错误的情况,实际使用时应注意输入的合法性。
众所周知, 任何一个表达式, 都可以用一棵表达式树来表示。 例如,
表达式 a+b*c, 可以表示为如下的表达式树:
+
/ \
a *
/ \
b c
现在, 给你一个中缀表达式, 这个中缀表达式用变量来表示(不含数字), 请你将这个中缀表达式用表达式二叉树的形式输出出来。
时间限制: 1000
内存限制: 65535
输入
输入分为三个部分。 第一部分为一行, 即中缀表达式(长度不大于 50)。
中缀表达式可能含有小写字母代表变量(a-z), 也可能含有运算符(+、-、 *、 /、 小括号), 不含有数字, 也不含有空格。 第二部分为一个整数 n(n < 10), 表示中缀表达式的变量数。 第三部分有 n 行, 每行格式为 C x, C 为变量的字符, x 为该变量的值。
输出
输出分为三个部分, 第一个部分为该表达式的逆波兰式, 即该表达式树的后根遍历结果。 占一行。 第二部分为表达式树的显示, 如样例输出所示。 如果该二叉树是一棵满二叉树, 则最底部的叶子结点, 分别占据横坐标的第 1、 3、 5、 7……个位置(最左边的坐标是 1), 然后它们的父结点的横坐标, 在两个子结点的中间。 如果不是满二叉树,则没有结点的地方, 用空格填充(但请略去所有的行末空格)。 每一行父结点与子结点中隔开一行, 用斜杠(/) 与反斜杠(\) 来表示树的关系。 /出现的横坐标位置为父结点的横坐标偏左一格, \出现的横坐标位置为父结点的横坐标偏右一格。 也就是说, 如果树高为 m, 则输出就有 2m-1 行。 第三部分为一个整数, 表示将值代入变量之后,该中缀表达式的值。 需要注意的一点是, 除法代表整除运算, 即舍弃小数点后的部分。 同时, 测试数据保证不会出现除以 0 的现象。
样例输入
a+b*c
3
a 2
b 7
c 5
样例输出
abc*+
+
/ \
a *
/ \
b c
37
以下是一个使用C语言编写的解决方案:
#include
#include
#include
// 表达式树的节点结构
typedef struct TreeNode {
char data;
struct TreeNode *left;
struct TreeNode *right;
} TreeNode;
// 创建表达式树节点
TreeNode* createNode(char data) {
TreeNode *node = (TreeNode *)malloc(sizeof(TreeNode));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
// 判断运算符的优先级
int getPriority(char operator) {
if (operator == '+' || operator == '-')
return 1;
else if (operator == '*' || operator == '/')
return 2;
else
return 0;
}
// 将中缀表达式转换为逆波兰式(后缀表达式)
void infixToPostfix(char *infix, char *postfix) {
int len = strlen(infix);
int index = 0;
char stack[len];
int top = -1;
for (int i = 0; i < len; i++) {
char ch = infix[i];
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
// 操作数直接放入后缀表达式
postfix[index++] = ch;
} else if (ch == '(') {
// 左括号入栈
stack[++top] = ch;
} else if (ch == ')') {
// 右括号,将栈中的运算符出栈,直到遇到左括号
while (top >= 0 && stack[top] != '(') {
postfix[index++] = stack[top--];
}
// 弹出左括号
top--;
} else {
// 运算符,根据优先级判断是否需要出栈
while (top >= 0 && stack[top] != '(' && getPriority(stack[top]) >= getPriority(ch)) {
postfix[index++] = stack[top--];
}
// 当前运算符入栈
stack[++top] = ch;
}
}
// 将栈中剩余的运算符出栈
while (top >= 0) {
postfix[index++] = stack[top--];
}
postfix[index] = '\0';
}
// 构建表达式树
TreeNode* buildExpressionTree(char *postfix) {
int len = strlen(postfix);
TreeNode *stack[len];
int top = -1;
for (int i = 0; i < len; i++) {
char ch = postfix[i];
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
// 操作数创建节点入栈
TreeNode *node = createNode(ch);
stack[++top] = node;
} else {
// 运算符,取出栈顶的两个节点作为子节点,构建当前节点,入栈
TreeNode *right = stack[top--];
TreeNode *left = stack[top--];
TreeNode *node = createNode(ch);
node->left = left;
node->right = right;
stack[++top] = node;
}
}
return stack[0];
}
// 后根遍历表达式树,得到逆波兰式
void postorderTraversal(TreeNode *node, char *result) {
if (node == NULL)
return;
postorderTraversal(node->left, result);
postorderTraversal(node->right, result);
result[strlen(result)] = node->data;
}
// 计算表达式树的值
int evaluateExpressionTree(TreeNode *node, int *values) {
if (node == NULL)
return 0;
if ((node->data >= 'a' && node->data <= 'z') || (node->data >= 'A' && node->data <= 'Z')) {
// 变量节点,返回对应的值
return values[node->data - 'a'];
} else {
// 运算符节点,根据运算符计算左右子树的值
int leftValue = evaluateExpressionTree(node->left, values);
int rightValue = evaluateExpressionTree(node->right, values);
switch (node->data) {
case '+':
```c
return leftValue + rightValue;
case '-':
return leftValue - rightValue;
case '*':
return leftValue * rightValue;
case '/':
return leftValue / rightValue;
}
}
return 0;
}
// 打印表达式树
void printExpressionTree(TreeNode *node, int level) {
if (node == NULL)
return;
printExpressionTree(node->right, level + 1);
for (int i = 0; i < level; i++)
printf(" ");
printf("%c\n", node->data);
printExpressionTree(node->left, level + 1);
}
int main() {
char infix[51];
fgets(infix, sizeof(infix), stdin);
infix[strcspn(infix, "\n")] = '\0';
int n;
scanf("%d", &n);
getchar();
int values[26] = {0};
for (int i = 0; i < n; i++) {
char variable;
int value;
scanf("%c %d", &variable, &value);
getchar();
values[variable - 'a'] = value;
}
char postfix[51] = {0};
infixToPostfix(infix, postfix);
TreeNode *root = buildExpressionTree(postfix);
char result[51] = {0};
postorderTraversal(root, result);
printf("%s\n", result);
printExpressionTree(root, 0);
int expressionValue = evaluateExpressionTree(root, values);
printf("%d\n", expressionValue);
return 0;
}
在给定的示例输入下,该程序将产生以下输出:
abc*+
+
/ \
a *
/ \
b c
37
该程序首先读取中缀表达式,然后读取变量数和变量值。接下来,它将中缀表达式转换为逆波兰式,并构建表达式树。然后,它打印逆波兰式、表达式树的图形表示以及计算的表达式值。