C/C++编程(1~8级)全部真题・点这里
1 2 3 4 5 6 7
#############################
1 # | # | # | | #
#####—#####—#—#####—#
2 # # | # # # # #
#—#####—#####—#####—#
3 # | | # # # # #
#—#########—#####—#—#
4 # # | | | | # #
#############################
(图 1)
# = Wall
| = No wall
- = No wall
图1是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。城堡被分割成m×n(m≤50,n≤50)个方块,每个方块可以有0~4面墙。
时间限制:1000
内存限制:65536
输入
程序从标准输入设备读入数据。第1、2行每行1个整数,分别是南北向、东西向的方块数。在接下来的输入行里,每个方块用一个数字(0≤p≤50)描述。用一个数字表示方块周围的墙,1表示西墙,2表示北墙,4表示东墙,8表示南墙。每个方块用代表其周围墙的数字之和表示。城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙。输入的数据保证城堡至少有两个房间。
输出
输出2行,每行一个数,表示城堡的房间数、城堡中最大房间所包括的方块数。结果显示在标准输出设备上。
样例输入
4
7
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13
样例输出
5
9
以下是一个用C语言编写的解决方案,实现了计算城堡的房间数和最大房间大小的功能:
#include
#define MAX_M 50
#define MAX_N 50
int castle[MAX_M][MAX_N]; // 城堡地图
int visited[MAX_M][MAX_N]; // 记录方块是否被访问过
int roomSize[MAX_M * MAX_N]; // 每个房间的大小
int maxRoomSize = 0; // 最大房间的大小
int roomCount = 0; // 房间数
// 方块的四个方向
const int WEST = 1;
const int NORTH = 2;
const int EAST = 4;
const int SOUTH = 8;
// 方块的坐标增量
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};
// 深度优先搜索遍历房间
void dfs(int x, int y) {
visited[x][y] = 1; // 标记为已访问
roomSize[roomCount]++; // 当前房间大小加一
maxRoomSize = (roomSize[roomCount] > maxRoomSize) ? roomSize[roomCount] : maxRoomSize;
// 遍历四个方向
for (int i = 0; i < 4; i++) {
// 判断当前方向是否有墙
if (!(castle[x][y] & (1 << i))) {
int nx = x + dx[i];
int ny = y + dy[i];
// 判断下一个方块是否合法且未访问过
if (nx >= 0 && nx < MAX_M && ny >= 0 && ny < MAX_N && !visited[nx][ny]) {
dfs(nx, ny);
}
}
}
}
int main() {
int m, n;
scanf("%d%d", &m, &n);
// 读取城堡地图
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &castle[i][j]);
}
}
// 遍历每个方块
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!visited[i][j]) {
roomCount++;
dfs(i, j);
}
}
}
printf("%d\n%d\n", roomCount, maxRoomSize);
return 0;
}
这个程序首先定义了一些常量和全局变量,包括城堡地图、方块访问状态、每个房间的大小、最大房间的大小和房间数等。
然后,程序通过深度优先搜索遍历每个房间。对于每个未访问过的方块,将其作为起点进行深度优先搜索。在搜索过程中,将已访问过的方块标记为已访问,同时统计当前房间的大小,并更新最大房间的大小。搜索完成后,房间数加一。
最后,程序输出房间数和最大房间的大小。
我们定义一个正整数a比正整数b优先的含义是:
*a的质因数数目(不包括自身)比b的质因数数目多;
*当两者质因数数目相等时,数值较大者优先级高。
现在给定一个容器,初始元素数目为0,之后每次往里面添加10个元素,每次添加之后,要求输出优先级最高与最低的元素,并把该两元素从容器中删除。
时间限制:2500
内存限制:131072
输入
第一行: num (添加元素次数,num <= 30)
下面10*num行,每行一个正整数n(n < 10000000).
输出
每次输入10个整数后,输出容器中优先级最高与最低的元素,两者用空格间隔。
样例输入
1
10 7 66 4 5 30 91 100 8 9
样例输出
66 5
以下是完整的C语言解决方案,使用优先队列(Priority Queue)实现了按照定义的优先级规则添加和删除元素,并输出优先级最高和最低的元素。
#include
#include
#include
#include
#define MAX_SIZE 10
// 结点定义
typedef struct {
int value; // 元素的值
int prime_factors; // 质因数的数量
} Node;
// 优先队列定义
typedef struct {
Node* heap; // 使用数组表示堆
int size; // 当前堆的大小
int max_size; // 堆的最大容量
} PriorityQueue;
// 创建一个新的结点
Node* createNode(int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->value = value;
newNode->prime_factors = 0;
return newNode;
}
// 交换两个结点
void swap(Node* a, Node* b) {
Node temp = *a;
*a = *b;
*b = temp;
}
// 判断一个数是否为质数
bool isPrime(int n) {
if (n <= 1) {
return false;
}
int sqrt_n = sqrt(n);
for (int i = 2; i <= sqrt_n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
// 计算一个数的质因数数量
int countPrimeFactors(int n) {
int count = 0;
for (int i = 2; i <= n; i++) {
if (n % i == 0 && isPrime(i)) {
count++;
}
}
return count;
}
// 初始化优先队列
PriorityQueue* createPriorityQueue(int max_size) {
PriorityQueue* pq = (PriorityQueue*)malloc(sizeof(PriorityQueue));
pq->heap = (Node*)malloc(max_size * sizeof(Node));
pq->size = 0;
pq->max_size = max_size;
return pq;
}
// 插入元素到优先队列
void insert(PriorityQueue* pq, Node* node) {
// 如果队列已满,先删除优先级最低的元素
if (pq->size == pq->max_size) {
int min_index = 0;
for (int i = 1; i < pq->max_size; i++) {
if (pq->heap[i].prime_factors < pq->heap[min_index].prime_factors) {
min_index = i;
} else if (pq->heap[i].prime_factors == pq->heap[min_index].prime_factors &&
pq->heap[i].value > pq->heap[min_index].value) {
min_index = i;
}
}
// 删除优先级最低的元素
free(pq->heap[min_index]);
pq->heap[min_index] = node;
} else {
pq->heap[pq->size++] = *node;
}
// 对堆进行自下而上的调整
int index = pq->size - 1;
while (index > 0) {
int parent = (index - 1) / 2;
if (pq->heap[index].prime_factors < pq->heap[parent].prime_factors) {
break;
} else if (pq->heap[index].prime_factors == pq->heap[parent].prime_factors &&
pq->heap[index].value <= pq->heap[parent].value) {
break;
}
swap(&pq->heap[index], &pq->heap[parent]);
index = parent;
}
}
// 删除优先队列中的优先级最高元素,并返回其值
int deleteMax(PriorityQueue* pq) {
if (pq->size == 0) {
return -1; // 队列为空
}
int max_value = pq->heap[0].value;
free(pq->heap[0]);
pq->heap[0] = pq->heap[pq->size - 1];
pq->size--;
// 对堆进行自上而下的调整
int index = 0;
while (true) {
int left_child = 2 * index + 1;
int right_child = 2 * index + 2;
int max_child = index;
if (left_child < pq->size &&
(pq->heap[left_child].prime_factors > pq->heap[max_child].primefactors ||
(pq->heap[left_child].prime_factors == pq->heap[max_child].prime_factors &&
pq->heap[left_child].value > pq->heap[max_child].value))) {
max_child = left_child;
}
if (right_child < pq->size &&
(pq->heap[right_child].prime_factors > pq->heap[max_child].prime_factors ||
(pq->heap[right_child].prime_factors == pq->heap[max_child].prime_factors &&
pq->heap[right_child].value > pq->heap[max_child].value))) {
max_child = right_child;
}
if (max_child == index) {
break;
}
swap(&pq->heap[index], &pq->heap[max_child]);
index = max_child;
}
return max_value;
}
int main() {
int num;
scanf("%d", &num);
PriorityQueue* pq = createPriorityQueue(MAX_SIZE);
for (int i = 0; i < num; i++) {
for (int j = 0; j < MAX_SIZE; j++) {
int n;
scanf("%d", &n);
Node* newNode = createNode(n);
newNode->prime_factors = countPrimeFactors(n);
insert(pq, newNode);
}
int max_value = deleteMax(pq);
int min_value = deleteMax(pq);
printf("%d %d\n", max_value, min_value);
}
return 0;
}
注意:由于输入数据量较大,为了避免超时,可以适当增大堆的最大容量(MAX_SIZE
)和质因数计算的上限(10000000
)。
给定一棵二叉树,求该二叉树的深度
二叉树深度定义:从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的节点个数为树的深度
时间限制:1000
内存限制:65535
输入
第一行是一个整数n,表示二叉树的结点个数。二叉树结点编号从1到n,根结点为1,n <= 10 接下来有n行,依次对应二叉树的n个节点。 每行有两个整数,分别表示该节点的左儿子和右儿子的节点编号。如果第一个(第二个)数为-1则表示没有左(右)儿子
输出
输出一个整型数,表示树的深度
样例输入
3
2 3
-1 -1
-1 -1
样例输出
2
以下是一个求二叉树深度的C语言解决方案,使用递归的方式遍历二叉树并计算深度:
#include
#include
// 二叉树节点定义
typedef struct TreeNode {
int val;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
// 创建一个新的二叉树节点
TreeNode* createNode(int val) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->val = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// 递归计算二叉树的深度
int maxDepth(TreeNode* root) {
if (root == NULL) {
return 0;
} else {
int leftDepth = maxDepth(root->left);
int rightDepth = maxDepth(root->right);
return 1 + (leftDepth > rightDepth ? leftDepth : rightDepth);
}
}
// 构建二叉树
TreeNode* buildTree(int n) {
TreeNode** nodes = (TreeNode**)malloc((n + 1) * sizeof(TreeNode*));
for (int i = 0; i <= n; i++) {
nodes[i] = createNode(i);
}
for (int i = 1; i <= n; i++) {
int left, right;
scanf("%d %d", &left, &right);
if (left != -1) {
nodes[i]->left = nodes[left];
}
if (right != -1) {
nodes[i]->right = nodes[right];
}
}
TreeNode* root = nodes[1];
free(nodes);
return root;
}
int main() {
int n;
scanf("%d", &n);
TreeNode* root = buildTree(n);
int depth = maxDepth(root);
printf("%d\n", depth);
return 0;
}
注意:根据题目描述,二叉树的节点编号从1到n,其中根节点为1。输入时按照节点编号的顺序给出节点的左儿子和右儿子的编号,如果没有左(右)儿子,则用-1表示。在构建二叉树时,我们使用了一个辅助数组nodes
来保存每个节点的指针,便于后续的连接操作。最后,我们调用maxDepth
函数计算二叉树的深度,并输出结果。
小明有很多猪,他喜欢玩叠猪游戏,就是将猪一头头叠起来。猪叠上去后,还可以把顶上的猪拿下来。小明知道每头猪的重量,而且他还随时想知道叠在那里的猪最轻的是多少斤。
时间限制: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
#define MAX_PIGS 20000
typedef struct {
int weight;
bool is_valid;
} Pig;
Pig pigs[MAX_PIGS];
int top;
void push(int weight) {
pigs[top].weight = weight;
pigs[top].is_valid = true;
top++;
}
void pop() {
if (top > 0) {
top--;
pigs[top].is_valid = false;
}
}
int min() {
int min_weight = -1;
for (int i = 0; i < top; i++) {
if (pigs[i].is_valid) {
if (min_weight == -1 || pigs[i].weight < min_weight) {
min_weight = pigs[i].weight;
}
}
}
return min_weight;
}
int main() {
char command[10];
top = 0;
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%s", command);
if (strcmp(command, "push") == 0) {
int weight;
scanf("%d", &weight);
push(weight);
} else if (strcmp(command, "pop") == 0) {
pop();
} else if (strcmp(command, "min") == 0) {
int min_weight = min();
if (min_weight != -1) {
printf("%d\n", min_weight);
}
}
}
return 0;
}
在这个解决方案中,我们使用了一个结构体数组pigs
来表示堆猪,每个元素包含猪的重量和是否有效的标志。变量top
表示堆顶的索引。
我们定义了三个函数:
push
函数用于将一头重量为weight
的猪叠到堆中,将其重量和有效标志保存在pigs
数组中,并更新top
。
pop
函数用于将堆顶的猪赶走,即将其有效标志设为false
,并更新top
。
min
函数用于计算堆中最轻的猪的重量,遍历pigs
数组并找到有效猪中的最小重量。
在main
函数中,我们读取输入的指令并根据指令调用相应的函数。如果是push
指令,我们读取猪的重量并调用push
函数;如果是pop
指令,我们调用pop
函数;如果是min
指令,我们调用min
函数并输出最轻猪的重量(如果有猪的话)。
请注意,我们假设输入的指令合法且不会导致堆栈溢出。