PAT甲级刷题记录-(AcWing)-Day15(模拟 8题 并查集 1题)
课程来源AcWing
其中AcWing中的题目为翻译好的中文题目
刷题列表
1008 Elevator
注意点
#include <iostream>
#include <cstring>
using namespace std;
int n;
int main() {
cin >> n;
int res = 0;
int cur = 0;
while (n--) {
int x;
cin >> x;
if (cur < x)res += (x - cur) * 6;
else res += (cur - x) * 4;
res += 5;
cur = x;
}
cout << res << endl;
return 0;
}
1011 World Cup Betting
英语单词
解析
注意点
#include <iostream>
#include <vector>
using namespace std;
double w, t, l;
int main() {
double res = 1;
for (int i = 0; i < 3; ++i) {
cin >> w >> t >> l;
double x = max(w, max(t, l));
if (x == w) cout << "W ";
else if (x == t) cout << "T ";
else cout << "L ";
res *= x;
}
printf("%.2lf\n", (res * 0.65 - 1) * 2);
return 0;
}
1014 Waiting in Line
解析
每个窗口用一个队列来维护
队列中存放的是每个人的服务完成时间
对于输入的所有人,依次插入队列
- 如果输入的序号在
n*m
之前,则按队列编号顺序找到排队人数最少的那个插入, 并计算当前队列的总共结束时间(8.00 + 队列中所有人的服务时间) - 如果是要在黄线后面排队的人,则找到完成时间最早的那个队列(对头元素最小的)
- 将目标队列出队,然后插入当前要去排队的人,并更新队列的总结束时间, 将当前人的结束时间加入哈希表
- 这里要判断一下办理的人是否在5.00前申请办理
- 最后根据哈希表查询每个人的完成时间即可
注意点
#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
const int N = 30;
int n, m, k, q;
queue<int> windows[N]; // n个窗口
unordered_map<int, int> map; // 顾客编号从1到k
int sum[N]; //每个窗口的总服务时间
int main() {
cin >> n >> m >> k >> q;
for (int i = 1; i <= k; ++i) {
int service;
cin >> service;
int target = 0;
for (int j = 0; j < n; ++j) {
//找需要插入的队列
if (i <= n * m) {
// 可以直接加入到队列中, 找排队人数最小的那个队列
if (windows[j].size() < windows[target].size()) target = j;
} else {
// 要先在黄线后面排队, 找第一个结束服务的队列
if (windows[j].front() < windows[target].front()) target = j;
}
}
// 此时target为要插入的队列
int cur_over = sum[target] + service; // 当前顾客的服务完成时间等于队列的总完成时间+自己要服务的时间
windows[target].push(cur_over);
sum[target] += service; // 更新队列的总结束时间
if (i > n * m) windows[target].pop();
if (sum[target] - service < 540) map[i] = sum[target];
}
while (q--) {
int id;
cin >> id;
if (map.count(id)) printf("%02d:%02d\n", map[id] / 60 + 8, map[id] % 60);
else puts("Sorry");
}
return 0;
}
1031 Hello World for U
英语单词
解析
用不等式先算出来n1
的最大取值, 然后按顺序划分输出即可
注意点
if(res[i][j]) cout << res[i][j];
else cout << " ";
#include <iostream>
const int N = 100;
using namespace std;
string s;
char res[N][N];
int main() {
cin >> s;
int n = s.size();
int n1 = min((n + 2) / 3, (n - 1) / 2);
int n2 = n + 2 - 2 * n1;
int idx = 0;
for (int i = 0; i < n1; ++i) {
res[i][0] = s[idx++];
}
for (int i = 1; i < n2; ++i) {
res[n1 - 1][i] = s[idx++];
}
for (int i = n1 - 2; i >= 0; i--) {
res[i][n2 - 1] = s[idx++];
}
for (int i = 0; i < n1; ++i) {
for (int j = 0; j < n2; ++j) {
if(res[i][j]) cout << res[i][j];
else cout << " ";
}
cout << endl;
}
return 0;
}
1041 Be Unique
英语单词
- lottery 彩票
- bet on 就…打赌
解析
注意点
#include <iostream>
#include <vector>
const int N = 10010;
using namespace std;
vector<int> num;
int st[N];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
num.push_back(x);
st[x]++;
}
bool has = false;
for (auto &x:num) {
if (st[x] == 1) {
cout << x;
has = true;
break;
}
}
if(!has) puts("None");
return 0;
}
1042 Shuffling Machine
注意点
void *memcpy(void *str1, const void *str2, size_t n)
- 从存储区 str2 复制 n 个字节到存储区 str1。
#include <iostream>
#include <cstring>
using namespace std;
int card[60], res[60], order[60], k;
void print(int x) {
if (x <= 13) cout << "S" << x;
else if (x <= 26) cout << "H" << x - 13;
else if (x <= 39) cout << "C" << x - 26;
else if (x <= 4 * 13) cout << "D" << x - 39;
else cout << "J" << x - 4 * 13;
}
int main() {
cin >> k;
for (int i = 1; i < 55; ++i) {
card[i] = i;
}
for (int i = 1; i < 55; ++i) {
cin >> order[i];
}
while (k--) {
memcpy(res, card, sizeof(res)); // card = res
for (int i = 1; i < 55; ++i) {
card[order[i]] = res[i];
}
}
print(card[1]);
for (int i = 2; i < 55; ++i) {
cout << " ";
print(card[i]);
}
return 0;
}
1047 Student List for Course
英语单词
解析
也可以用 vector<string> lessons[N]
来存储
注意点
一开始有一个点超时了,然后把cin
都改成scanf printf
就对了
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
unordered_map<int, vector<string>> map;
int n, k;
int main() {
scanf("%d %d", &n, &k);
while (n--) {
char name[10];
scanf("%s", name);
int cnt;
cin >> cnt;
while (cnt--) {
int course;
scanf("%d", &course);
map[course].push_back(name);
}
}
for (int i = 1; i <= k; ++i) {
auto stu_list = map[i];
printf("%d %d\n", i, stu_list.size());
sort(stu_list.begin(), stu_list.end());
for (auto &item:stu_list) {
printf("%s\n", item.c_str());
}
}
return 0;
}
1054 The Dominant Color
英语单词
- the resolutions of the image 图像的分辨率
解析
注意点
vector<pair<int,int>>
的排序先按第一个关键字的升序,再按第二个关键字的升序, 所以这里我们要得到降序, 在插入的时候加个负号就好了
这种方法有点麻烦,还是后面一种好
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
unordered_map<int, int> map;
vector<pair<int, int>> colors;
int m, n;
int main() {
cin >> m >> n;
while (n--) {
for (int i = 0; i < m; ++i) {
int c;
cin >> c;
map[c]++;
}
}
for (auto &item:map) {
colors.push_back({
-item.second, item.first,});
}
sort(colors.begin(), colors.end());
cout << colors[0].second << endl;
return 0;
}
一种简单的写法, 在输入过程中看看当前颜色有没有超过一半的像素数量即可
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
unordered_map<int, int> map;
int m, n;
int main() {
cin >> m >> n;
for (int i = 0; i < n * m; ++i) {
int x;
cin >> x;
if (++map[x] > n * m / 2) {
cout << x;
break;
}
}
return 0;
}
1107 Social Clusters
注意点
注意从序号从1开始的一些问题
#include <iostream>
#include <vector>
#include <algorithm>
const int N = 1010;
using namespace std;
int n;
vector<int> hobby[N];
int p[N];
int cnt[N];
int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main() {
cin >> n;
for (int i = 1; i < n + 1; ++i) {
int k;
scanf("%d: ", &k);
while (k--) {
int id;
cin >> id;
hobby[id].push_back(i);
}
}
// 初始化并查集
for (int i = 1; i < n + 1; ++i) {
p[i] = i;
}
// 合并并查集
for (int i = 1; i < N; ++i) {
if (hobby[i].size() > 0) {
int a = hobby[i][0];
for (int j = 1; j < hobby[i].size(); ++j) {
int b = hobby[i][j];
// 把所有的b都合并到a里面去
p[find(a)] = find(b);
}
}
}
// 统计相同祖先的集合数量
for (int i = 1; i < n + 1; ++i) {
cnt[find(i)]++;
}
sort(cnt + 1, cnt + n + 1, greater<int>()); // 从大到小排序
int k = 1;
// 找前k个不为0的值,记录集群的数量
while (cnt[k]) k++;
cout << k << endl;
cout << cnt[1];
for (int i = 2; i < k; ++i) {
cout << " " << cnt[i];
}
return 0;
}