攀拓计算机能力测评-程序设计-2023年冬季考试 - 乙级

 目录

B-4 方格填数

B-5 堆栈中的最大值

B-4 方格填数

2014 年哈佛-麻省理工数学竞赛中一道题是这样的:将正整数 1, 2, ..., 64 填入 8×8 的方格棋盘中,使得对任何 1≤i<64,i 和 i+1 都必须填在两个具有公共边的方格中。求棋盘上对角线中所填数的和的最大值。(注意:两个对角线都要考虑;64 和1 也必须填在两个具有公共边的方格中。)
这题有点难…… 幸好我们并不要求你写程序解决这个问题。
你的任务是:对任一给定的数字填充方案,判定其是否满足填充的条件,并且在所有给出的方案中,找出满足条件的、且对角线数字和最大的那个方案。

输入格式:

输入在一行中首先给出两个正整数 n(≤100) 和 m(≤20),分别为棋盘的规模(即棋盘有 n×n 个方格)和输入的方案数量。因为容易证明奇数 n 一定不存在满足条件的解,所以题目保证给出的 n 都是偶数。
随后给出 m 个填充方案,每个方案占 n 行,每行 n 个不超过 n2 的数字。同行数字间以空格分隔。

输出格式:

在一行中首先输出满足条件的、且对角线数字和最大的方案数。随后一行中按照递增序输出这些方案的编号(编号按输入的顺序从 1 到 m)。
注意每行数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

4 5
16 1 2 3
15 14 13 4
10 11 12 5
9 8 7 6
16 1 2 3
15 14 13 4
10 11 12 5
9 8 7 10
15 16 1 2
14 13 4 3
11 12 5 6
10 9 8 7
3 4 5 6
2 13 12 7
1 14 11 8
16 15 10 9
10 5 4 3
7 12 13 2
8 11 14 1
9 6 15 16

输出样例:

2
1 4

条件提取

  1. (注意:两个对角线都要考虑;64 和1 也必须填在两个具有公共边的方格中。)
  2. 两个正整数 n(≤100) 和 m(≤20)
  3. 将正整数 1, 2, ..., 64 填入 8×8 的方格棋盘中,使得对任何 1≤i<64,i 和 i+1 都必须填在两个具有公共边的方格中。
  4. 。求棋盘上对角线中所填数的和的最大值。
  5. 在一行中首先输出满足条件的、且对角线数字和最大的方案数。随后一行中按照递增序输出这些方案的编号(编号按输入的顺序从 1 到 m)。
    注意每行数字间以 1 个空格分隔,行首尾不得有多余空格。

思路

        当n为4时,最大的元素为16  , 16需要和1相邻 ,  只需要判断每个元素的上下左右四个位置元素即可

        j 为行遍历变量 k 为列遍历变量 , i从0到n , j从0到n

         int x[4] = {j - 1, j , j, j + 1}, y[4] = {k, k - 1, k + 1, k};  x,y数组为上下左右四个相邻元素的位置下标 . 如果矩阵合法则判断两个对角线元素之和是否大于max   大于则清空原有最大和编号容器 , 然后把本编号添加进去

        最后输出合法矩阵总数,然后按增序输出编号  注意即便总数为0也要再输出一个空行

       

#include<bits/stdc++.h>
using namespace std;
int main(void) {
	int n, m, max = 0;
	map<int, int> v;
	scanf("%d %d", &n, &m);
	getchar();
	for (int i = 0; i < m; ++i) {
		int a[n][n];
		for (int j = 0; j < n; ++j)
			for (int k = 0; k < n; ++k) {
				scanf("%d", &a[j][k]);
				getchar();
			}
		bool F = 1;
		for (int j = 0; j < n; ++j)
			for (int k = 0; k < n; ++k) {
				int x[4] = {j - 1, j , j, j + 1}, y[4] = {k, k - 1, k + 1, k};
				bool f = 0;
				for (int q = 0; q < 4; ++q)
					//若坐标合法
					if (x[q] > -1 && x[q] < n && y[q] > -1 && y[q] < n)
						if (a[j][k] == a[x[q]][y[q]] % (n * n) + 1) {
							f = 1;
							break;
						}
				if (!f) {
					F = 0;
					break;
				}
			}
		if (F) {
			int sum = 0;
			for (int j = 0; j < n; ++j) {
				sum += a[j][j];
				sum += a[n - j - 1][j];
			}
			if (sum > max) {
				max = sum;
				v.clear();
				v[i + 1] = 1;
			} else if (sum == max) v[i + 1] = 1;
		}
	}
	bool f = 1;
	printf("%d\n", v.size());
	for (auto a : v) {
		printf("%s%d", f ? "" : " ", a.first);
		f = 0;
	}
    printf("\n");
	return 0;
}

B-5 堆栈中的最大值

堆栈是一种后进先出的线性结构。本题要求你在实现普通堆栈的进栈(Push)和出栈(Pop)功能时,外加一个查看最大值(PeekMax)的功能。重点是,这个额外的功能不能影响整个堆栈的操作效率。

输入格式:

输入第一行首先给出一个正整数 n (≤105),是堆栈操作的数量。随后 n 行,每行给出一个操作,格式为:

  • Push X 表示将值为 X 的元素入栈,其中 X 是绝对值不超过 230 的整数;
  • Pop 表示将栈顶元素出栈;
  • PeekMax 表示要求返回此刻堆栈中最大元素的值。

输出格式:

对输入中的每个操作,按照要求执行操作。对每个 Pop,在一行中输出出栈的元素值;对每个 PeekMax,在一行中输出此刻堆栈中最大元素的值。若执行 Pop 或 PeekMax 时堆栈是空的,则对应输出 ERROR,并且不执行该操作。
题目保证至少有一行输出。

输入样例:

11
Pop
Push 34
Push 28
PeekMax
Push 84
PeekMax
Pop
PeekMax
Pop
Pop
PeekMax

输出样例:

ERROR
34
84
84
34
28
34
ERROR

思路

        双栈   一个存储元素的栈  另一个存储最大值的栈

        如果push的元素大于等于上一个最大元素值  则入存储最大值的栈中  小于的不用入存储最大值的栈       无论push的元素与上一个最大元素值大小关系如何都必须入存储元素的栈

        出栈顶元素时候如果是最大值元素 则对应存储最大值的栈也要出栈顶元素

        输出栈内最大值的时候,只需要输出存储最大值的栈的栈顶元素

#include<bits/stdc++.h>
using namespace std;
int main(void) {
	int n, t = 0;
	scanf("%d", &n);
	getchar();
	string s;
	queue<int> q;
	vector<int> v;
	int a[n], b[n], top = -1, mtop = -1;
	for (int i = 0; i < n; ++i) {
		cin >> s;
		if (s == "Push") {
			cin >> t;
			if (top == -1)
				b[++mtop] = t;
			else if (t >= b[mtop]) b[++mtop] = t;
			a[++top] = t;
		} else if (s == "PeekMax") {
			if (top == -1) printf("ERROR\n");
			else printf("%d\n", b[mtop]);
		} else if (s == "Pop") {
			if (top == -1) printf("ERROR\n");
			else {
				printf("%d\n", a[top]);
				if (a[top] == b[mtop]) --mtop;
				--top;
			}
		}
	}
	return 0;
}

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值