2022年SCAU计算智能题库

目录

 头文件及宏定义

基础

18104 练习使用多case解题

注意事项:

代码实现:

递归和分治 (Recursion and Divide and Conquer)

1142 巡逻的士兵

注意事项: 

代码实现:

18441 偷懒的士兵

注意事项:

代码实现:

18442 偷懒的士兵2

注意事项:

代码实现:

19144 偷懒的士兵3

注意事项: 

代码实现:

排序和优先队列 (Sorting and Priority Queue)

18105 银行的叫号顺序

注意事项:

代码实现:

18216 银行服务

注意事项:

代码实现:

18107 校赛排名

注意事项:

代码实现:

18290 校赛排名2

注意事项: 

代码实现:

暴力枚举 (Brute Force)

18443 除法等式

注意事项:

代码实现:

1079 三角形

注意事项

代码实现:

18444 分数拆分

注意事项:

代码实现:

动态规划 (Dynamic Programming)

19116 丑数

注意事项:

代码实现:

18005 它不是丑数

注意事项:

代码实现:

18308 最长公共子序列

注意事项:

代码实现:

8615 快乐

注意事项:

代码实现:

回溯算法 (BackTracking)

18124 N皇后问题

注意事项:

代码实现:

19010 最小的特殊数字

注意事项:

代码实现:

搜索 (Search)

18276 走迷宫

注意事项:

代码实现:

18440 走迷宫2

注意事项:

代码实现:

实用类数据结构 (Pratical Data Structure)

18130 繁忙的公路

注意事项:

代码实现:

18233 万湖之国的形成

注意事项:

代码实现:

贪心算法 (Greedy)

18118 勇者斗恶龙

注意事项:

代码实现:

--------------------------------------------------------------------------------------------------------

  •  头文件及宏定义

  • #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <string>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    
    using namespace std;
    #define IOS ios::sync_with_stdio(0), cin.tie(0);
    typedef long long ll;
  • 基础

18104 练习使用多case解题

时间限制:1000MS  代码长度限制 : 10KB

Description
多CASE的问题在般有3种情形:(1)有一个数字开始表明CASE数目;(2)以特殊标志表示结束;(3)要求处理到最后一行。
现要求你在程序一次运行中,依次处理上述3种情况。

有三批测试数据,第1批测试数据,开头会以一个数字告之该批CASE数量,每一个CASE是两个正整数;
第1批测试数据结束后,紧接着是第2批数据,每一个CASE同样是两个正整数,第2批测试数据以两个0结束;
第2批测试数据结束后,紧接着是第3批数据,每一个CASE也是两个正整数,第3批测试数据一直到数据输入结束;

要求,每一个CASE,输出两数的最小公倍数
第1批测试数据处理完毕时,输出“group 1 done”
第2批测试数据处理完毕时,输出“group 2 done”
第3批测试数据处理完毕时,输出“group 3 done”

输入格式
有三批测试数据,第1批测试数据,开头会以一个数字告之该批CASE数量,每一个CASE是两个正整数(最大2的31次方);
第1批测试数据结束后,紧接着是第2批数据,每一个CASE同样是两个正整数,第2批测试数据以两个0结束;
第2批测试数据结束后,紧接着是第3批数据,每一个CASE也是两个正整数,第3批测试数据一直到数据输入结束;

输出格式
要求,每一个CASE,输出两数的最小公倍数
第1批测试数据处理完毕时,输出“group 1 done”
第2批测试数据处理完毕时,输出“group 2 done”
第3批测试数据处理完毕时,输出“group 3 done”

输入样例
2
6 10
5 12
8 16
12 18
8 4
0 0
4 5
4 6

输出样例
30
60
group 1 done
16
36
8
group 2 done
20
12
group 3 done

 

注意事项:

该题注意数据都用long long

 

代码实现:

ll GCD(ll num1, ll num2) { // 最大公约数
	ll r; 
	while (num1 % num2) {
		r = num1 % num2;
		num1 = num2;
		num2 = r;
	}
	return num2;
}

ll LCM(ll num1, ll num2) { // 最小公倍数
	return ((num1 * num2) / GCD(num1, num2));
}

int main() {
	IOS;
	ll num1, num2;
	// 有给定Case的数量
	ll n; cin >> n;
	while (n--) {
		cin >> num1 >> num2;
		cout << LCM(num1, num2) << endl;
	}
	cout << "group 1 done" << endl;

	// 没有给定Case的数量,但是有输入结束的标志
	for (;;) {
		cin >> num1 >> num2;
		if (num1 == 0 && num2 == 0) {
			break;
		}
		cout << LCM(num1, num2) << endl;
	}
	cout << "group 2 done" << endl;

	// 没有给定Case的数量,读取数据到最后一行
	while (cin >> num1 >> num2) {
		cout << LCM(num1, num2) << endl;
	}
	cout << "group 3 done" << endl;
	return 0;
}
  • 递归和分治 (Recursion and Divide and Conquer)

1142 巡逻的士兵

时间限制 : 1000MS  代码长度限制 : 10KB
Description
有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。

现要求统计按这样的方法,总共可能有多少种不同的正好三个士兵去侦察的士兵组合方案。

注 : 按上法得到少于三士兵的情况不统计。

1 <= N <= 2的32次方 - 1

输入格式
有多行(可能有上百行,尽量优化代码),每行一个数字N,最后一行是0

输出格式
对每一行的数字N,输出针对N的方案数
直到没有数字

输入样例
10
4
0

输出样例
2
0

 

注意事项: 

该题数据量很大,需要使用备忘录 (memo) 来记录计算过的结果来减少重复计算

 

代码实现:

constexpr auto MAX = 1000000; // 定义限制
vector<int> memo(MAX, 0); // 备忘录

int solve(int n) {
	if (n < MAX && memo[n] != 0) { // 在备忘录中的计算直接返回之前计算的结果
		return memo[n];
	}
	if (n < 3) { // 最后剩下少于3个士兵的情况不用去巡逻
		return 0;
	}
	if (n == 3) { // 最后剩下刚好3个士兵都要去巡逻,为一个方案
		return 1;
	}
	int res = solve(n / 2) + solve((n + 1) / 2); // 最终的结果是去掉偶数站位的士兵的方案数加上去掉奇数站位的士兵的方案数
	if (n < MAX) { 
		memo[n] = res;
	}
	return res;
}


int main() {
	IOS;
	int n;
	while (cin >> n && n) {
		cout << solve(n) << endl;
	}
	return 0;
}

18441 偷懒的士兵

时间限制 : 1000MS  代码长度限制 : 10KB

Description
有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现有一个“聪明”的士兵,经常通过选择站在合适的初始位置,成功避免被选中去侦察。这引起了陈教官的注意。

陈教官希望你编写一个程序,当给定士兵数之后,输出有多少个位置上的士兵是不可能被选中去巡逻的。

注 : 按上法得到少于三士兵的情况不用去巡逻。

1 <= N <= 21亿

输入格式
有多行(可能有上百行,请尽量优化代码),每行一个数字N,最后一行是0

输出格式
对每一行的数字N,不可能被选中去巡逻的位置数
直到没有数字

输入样例
10
6
0

输出样例
4
0


注意事项:

 该题数据量很大,需要使用备忘录 (memo) 来记录计算过的结果来减少重复计算

 

代码实现:

#define MAX 1000000
vector<int> memo(MAX, 0);
int solve(int n) {
	if (n < MAX && memo[n]) {
		return memo[n];
	}
	if (n < 3) {
		return 0;
	}
	if (n == 3) {
		return 1;
	}
	int res = solve(n / 2) + solve((n + 1) / 2);
	if (n < MAX) {
		memo[n] = res;
	}
	return res;
}

int main() {
	IOS;
	int n;
	while (cin >> n && n) {
		cout << n - 3 * solve(n) << endl; // 要得到不会选去巡逻的士兵数量,即是所有士兵的数量减去 3 * 士兵去巡逻的方案数(每次巡逻都是3个人,所以乘以3)
	}
	return 0;
}

18442 偷懒的士兵2

时间限制 : 1000MS  代码长度限制 : 10KB

Description
有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现有一个“聪明”的士兵,经常通过选择站在合适的初始位置,成功避免被选中去侦察。这引起了陈教官的注意。陈教官希望你编写一个程序,当给定士兵数之后,输出不可能被选中去巡逻的最少编号位置(如果不存在不可能被选中的位置,则输出0)。

注 : 按上法得到少于三士兵的情况不用去巡逻。

1 <= N <= 100000

输入格式
有多行(不多于20行),每行一个数字N,最后一行是0

输出格式
对每一行的数字N,不可能被选中去巡逻的最小位置
直到没有数字

输入样例
9
6
0

输出样例
2
0


注意事项:

 

代码实现:

int solve(int n, int _min, int step) {
	if (n < 3) { // 此时不用去巡逻,得到的结果即为此时队伍的第一名士兵的编号
		return _min;
	}
	if (n == 3) { // 此时都要去巡逻,无法得到结果,返回INT32_MAX来排除答案
		return INT32_MAX;
	}
	int deleteOdd = solve(n / 2, _min + step, 2 * step); // 删除掉占位为奇数的士兵,此时第一名士兵的编号为之前第一名士兵的编号加上一个跨度
	int deleteEven = solve((n + 1) / 2, _min, 2 * step); // 删除掉占位为偶数的士兵, 此时第一名的士兵的编号不变
	return min(deleteOdd, deleteEven); // 取最小
}

int main() {
	IOS;
	int n;
	while (cin >> n && n) {
		int result = solve(n, 1, 1);
		cout << (result < INT32_MAX ? result : 0) << endl;
	}
	return 0;
}

19144 偷懒的士兵3

时间限制 : 1000MS  代码长度限制 : 10KB

Description
有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现有一个“聪明”的士兵,经常通过选择站在合适的初始位置,成功避免被选中去侦察。这引起了陈教官的注意。陈教官希望你编写一个程序,当给定士兵数,以及位置编号,判断站在该位置编号的战士是否可能被抽中巡逻。

注 : 按上法得到少于三士兵的情况不用去巡逻。

1 <= N <= 100000

输入格式
有多行(不多于10000行),每行两个数字,第一个数字是士兵人数,第二个数字是位置编号,最后一行是两个0,表示结束

输出格式
对每一行输入,输出一行结果,能被抽中输出Y,不能抽中输出N
最后一行两个0不需要

输入样例
4 1
5 1
0 0

输出样例
N
Y

 

注意事项: 

 

代码实现:

bool Check(int n, int m) {
	if (n < 3) {
		return false;
	}
	if (n == 3) {
		return true;
	}
	if (m % 2) { // 如果站位是奇数
		return Check((n + 1) / 2, (m + 1) / 2); // 去除站位是偶数的士兵
	}
	else {
		return Check(n / 2, m / 2); // 去除站位是奇数的士兵
	}
}
int main() {
	IOS;
	int n, m;
	while (cin >> n >> m && n && m) {
		cout << (Check(n, m) ? 'Y' : 'N') << endl;
	}
	return 0;
}
  • 排序和优先队列 (Sorting and Priority Queue)

18105 银行的叫号顺序

时间限制 : 8000MS  代码长度限制 : 10KB

Description
银行的叫号过程是一个优先队列的典型应用,假设,银行有4类客户,分别用优先级1,2,3,4表示,级别越高则更优先得到服务,例如,当前有三个人排队,两个1级客户,一个3级客户,则银行叫号时,3级客户将先得到服务,即使另两个1级有客户比他先到。当多个同级的客户将获得服务时,由先到的客户先得到服务。

假设,银行只有一个服务窗口,一次只能服务一个客户,假设该窗口每5分钟服务一个客户,即叫号的时刻分别为0分钟、5分钟、10分钟、.....如果在叫号的时侯,没有客户,银行职员会去喝杯咖啡或上个洗手间,5分钟后再继续叫号。

银行给出一系列客户到来的记录,每条记录包括“客户到来的时”,“客户等级”,“客户姓名”(由一个单词构成),请输出银行服务的客户的顺序。

输入格式
第一数字是客户的数量n(n <= 100000)此后,每一行是一个客户来访信息,包括3个数字,到来的时刻(分钟整点, 最大10的8次方)、等级、姓名(最多20个字母)(已经按到来时刻排序)

输出格式
按服务的先后顺序输出客户的姓名

输入样例
4
0 1 John
3 1 Smith
3 1 Tom
4 2 Flod

输出样例
John
Flod
Smith
Tom

注意事项:

代码实现:

int main() {
	IOS;
	int arrivalTime, level; string name;
	priority_queue<pair<int, string>> q; // 排队的队列
	const int levelIndex = 100000; // 客户等级所占比重的参数值
	int timeIndex = 99999; // 时间所占的参数值,且随着时间推移,该参数会递减
	int realTime = 0; // 实时的时间
	int numberOfClient; cin >> numberOfClient;
	while (numberOfClient--) {
		cin >> arrivalTime >> level >> name;
		for (;;) {
			if (arrivalTime <= realTime) {
				q.push(make_pair(level * levelIndex + timeIndex, name));
				timeIndex--;
				break;
			}
			if (!q.empty()) {
				cout << q.top().second << endl;
				q.pop();
			}
			realTime += 5;
		}
	}
	while (!q.empty()) {
		cout << q.top().second << endl;
		q.pop();
	}
	return 0;
}

18216 银行服务

时间限制 : 8000MS  代码长度限制 : 10KB

Description
银行通过叫号来决定服务用户的顺序,假设,银行有4类客户,分别用优先级1,2,3,4表示,级别越高则更优先得到服务,例如,当前有三个人排队,两个1级客户,一个3级客户,则银行叫号时,3级客户将先得到服务,即使另两个1级的客户比他先到。当多个同级的客户将获得服务时,由先到的客户先得到服务。

假设,银行只有一个服务窗口,一次只能服务一个客户,假设该窗口每5分钟服务一个客户,即叫号的时刻分别为0分钟、5分钟、10分钟、.....如果在叫号的时侯,没有客户,银行职员会去喝杯咖啡或上个洗手间,5分钟后再继续叫号。

有一种情况,银行工作到一定时间是要下班的,所以到一定时间,如果后面还有客户,将不再提供服务。

银行给出一系列客户到来的记录,每条记录包括“客户到来的时间”,“客户等级”,“客户姓名”(由一个单词构成),请输出该银行这一轮服务的客户的顺序。

输入格式
第一行两个数字,第一数字是客户的数量n(n <= 100000),第二个数字是银行关门的时间,到这个时间,即关门,该点及之后,不再叫号,但之前已经叫号的客户会继续服务到完结。
此后,每一行是一个客户来访信息,包括3个数字,到来的时刻(分钟整点, 最大10的8次方)、等级、姓名(最多20个字母)(已经按到来时刻排序,注意:同一时刻可能会同时到来多个客户,这时若为同等级的,数据出现得早的稍早得到服务)

输出格式
按服务的先后顺序输出客户的姓名

输入样例
4 12
0 1 John
3 1 Smith
3 1 Tom
4 2 Flod

输出样例
John
Flod
Smith

注意事项:

该题相比上一题只是多了一个时间的限制

代码实现:

int main() {
	IOS;
	priority_queue<pair<int, string>> q;
	c
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值