PAT(乙级)2021年春季考试7-1 打印三角形拼图 简单题7-2 赌马 到终点花的时间最少的前三名7-3 拼题 A 是真爱 字符串处理7-4 素数等差数列 暴力7-5 实验室使用排期 经典贪心

宝剑锋从磨砺出 梅花香自苦寒来

7-1 打印三角形拼图 简单题

#include<bits/stdc++.h>
using namespace std;
int main(void) {
	int L;
	char a, b, c;
	cin >> L >> a >> b >> c;
	for (int i = 0; i < L; ++i) {
		for (int j = 0; j < i; ++j)
			cout << b;
		cout << c;
		for (int j = 0; j < L - i-1; ++j)
			cout << a;
		cout << endl;
	}
	return 0;
}

7-2 赌马 到终点花的时间最少的前三名

#include<bits/stdc++.h>
using namespace std;
bool cmp(pair<int, double> a, pair<int, double> b) {
	if (a.second != b.second)
		return a.second < b.second;
	else return a.first < b.first;
}
int main(void) {
	int n, id, len, rate;
	cin >> n;
	vector<pair<int, double>> v;
	for (int i = 0; i < n; ++i) {
		cin >> id >> len >> rate;
		double time = 1.0 * len / rate;
		v.push_back({id, time});
	}
	sort(v.begin(), v.end(), cmp);
	for (int i = 0; i < 3; ++i) {
		if (i) cout << " ";
		cout << v[i].first;
	}
	return 0;
}

7-3 拼题 A 是真爱 字符串处理

P(p)intia左侧和右侧如果有字符那必须是空格 和英文逗号 和 英文的句号   左右两侧可以没有字符但是有字符必须是以上三种

判断数量即可

#include<bits/stdc++.h>
using namespace std;
int main(void) {
	string s;
	int c = 0;
	getline(cin, s);
	if (s.length() > 5) {
		for (int i = 0; i + 5 < s.length();) {
			if ((s[i] == 'p' || s[i] == 'P') && s[i + 1] == 'i' && s[i + 2] == 'n' && s[i + 3] == 't' && s[i + 4] == 'i' && s[i + 5] == 'a' && (s[i - 1] == ' ' || s[i - 1] == ',' || s[i - 1] == '.' || i - 1 < 0) && (s[i + 6] == ' ' || s[i + 6] == ',' || s[i + 6] == '.' || i + 6 >= s.length())) {
				++c;
				i += 6;
			} else ++i;
		}
	}
	printf("%d\n", c);
	if (c == 0) printf("wu gan");
	else if (c < 4) printf("you ai");
	else if (c > 3) printf("zhen ai la");
	return 0;
}

7-4 素数等差数列 暴力

说是暴力,,可不要想当然纯粹暴力  即便是1000ms的时间要求  如果暴力层数太多也会超时(别问我怎么知道的)

如何求最大的差? 第一项设为A0  第n项设为An  求等差d=(An-A0)/(n-1) 

我们就以此公式求出可能得最大差 因为实际上不一定我们用此公式求出来的查就是最大的差

所以我们从最大的差开始遍历 , 如果其有符合n项的等差数列 就不再向下遍历  找到其合法的最大的首数的等差书列举即可

我一开始先求出全部的素数然后i j双层遍历 先用i  j 确定等差  但是这样必须全部遍历完才能知道最大的差是什么    而用公式求出可能得最大的等差,如果其有合法等差序列则直接break不用再做多余遍历了

flag[]数组存储bool值  flag[i]==1 表示i为素数 0表示i不是素数

arr存储不大于maxp的全部素数

变量i用于对arr进行遍历 

md为最大的差

max为最大的差的序列里面的最大首数

最后根据md  和 max max+=md累加输出n项即可

n为1或者2 len为1的时候特判一下

#include<bits/stdc++.h>
using namespace std;
int main(void) {
	int n, maxp, max = 0;
	scanf("%d %d", &n, &maxp);
	getchar();
	int arr[maxp], len = 0;
	int flag[maxp + 100] = {0};
	for (int i = 2; i <= maxp; ++i) {
		bool f = 1;
		for (int j = 2; j * j <= i; ++j)
			if (i % j == 0) {
				f = 0;
				break;
			}
		if (f) {
			arr[len++] = i;
			flag[i] = 1;
		}
	}
	if (n == 1 || len <= 1) printf("%d", arr[len - 1]);
	else if (n == 2) printf("%d %d", arr[0] , arr[len - 1]);
	else {
		int md = (arr[len - 1] - arr[0]) / (n - 1);
		bool f = 0;
		for (md; md > 0; --md) {
			for (int i = 0; i <= len - n; ++i) {
				if (flag[arr[i] + md]) {
//					cout << "-----------此时md:" << md << " 此时i:" << arr[i] << endl;
					int l = arr[i] + md + md, c = 2;
					while (l <= maxp && flag[l]) {
						++c;
//							cout << "此md:" << md << " 此i:" << arr[i]  << " 此时l:" << l << " 此c:" << c << endl;
						if (c == n) {
							f = 1;
							if (arr[i] > max) max = arr[i];
							break;
						}
						l += md;
					}
				}
			}
			if (f) {
				printf("%d", max);
				for (int k = 1; k < n; ++k)
					printf(" %d", max += md);
				break;
			}
		}
		if (!f) printf("%d", arr[len - 1]);
	}
	return 0;
}

7-5 实验室使用排期 经典贪心

思路

        0点->24点  时间轴左侧为早点时间 右侧为晚时间

        逆推思想 最终的正确结果申请序列中 最早结束的一定包含在内  我们假设一个不冲突的申请序列(不包含最左侧) 其如果最早结束的申请不与最左侧冲突则左侧一定被包含 因为不冲突嘛  如果冲突 则与最左侧申请冲突的申请一定不能被选上 因为最左侧的申请一定可以与与它冲突的申请后面的申请不冲突   其后也是如此类推

        贪心嘛 如果不知道贪心基本思路的请去百度 和 看洛谷的贪心专题库 有一道跟这个十分类似的题

        按照结束时间从小到大排序    然后以最先结束的申请为起始进行贪心  每次都选择最左侧合法的申请  最后就是最优解

        因为最后的结果中最早结束的申请肯定被包含 

第一次选择最左侧合法的,那有人问?下面举例:  下面统一用一个数字表示起始时间和结束时间

1:        strart:  1   end: 2

  2:      start:1.5  end: 2.5

   3:    start:2.5 end:2.6

   4:     start: 2.6 end:3

以四次个申请

        第一次当然选1  为什么不选2  如果选2, 合法序列为2 3 4     那第一次选1也是 1 3 4一共三个

那如果是下面这样情况呢?

1:        strart:  1   end: 2

  2:      start:1.5  end: 2.5

   3:    start:2.3 end:2.4

   4:     start: 2.6 end:3

如果第一次你选了2 序列为2 4  ,,,选1则为1 3 4

以此类推,下次再选第二个的时候 就可以当成选第一个 但要跟前面的不冲突

#include<bits/stdc++.h>
using namespace std;
bool cmp(pair<int, int> a, pair<int, int> b) {
	return a.second < b.second;
}
int main(void) {
	int n, h1, h2, m1, m2, s1, s2, st, en;
	scanf("%d", &n);
	getchar();
	vector<pair<int, int>> v;
	for (int i = 0; i < n; ++i) {
		scanf("%d:%d:%d %d:%d:%d", &h1, &m1, &s1, &h2, &m2, &s2);
		getchar();
		st = h1 * 3600 + m1 * 60 + s1;
		en = h2 * 3600 + m2 * 60 + s2;
		v.push_back({st, en});
	}
	int c = 1;
	sort(v.begin(), v.end(), cmp);
	int l = 0;
	for (int j = 1; j < n; ++j) {
		if (v[j].first >= v[l].second) {
			l = j;
			++c;
		}
	}
	cout << c;
	return 0;
}
  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值