目录
总结:
A-1 Trap
Input Specification:
Output Specification:
Sample Input:
Sample Output:
题意:
思路:
AC代码:
A-2 Queue Using Two Stacks
Input Specification:
Output Specification:
Sample Input:
Sample Output:
题意:
AC代码:
A-3 Rank of Binary Tree
Input Specification:
Output Specification:
Sample Input:
Sample Output:
题意:
思路:
A-4 Big Number
Input Specification:
Output Specification:
Sample Input:
Sample Output:
题意:
思路:
(26分)
正解:
AC代码
总结:
第一次打PAT甲级可能也是最后一次打了,可能因为今天蓝桥国赛,就我一个人考,考场上主要还是不太适应英文题面,老是看样例猜题意,第一个题一看是个地图乍以为是个搜索,读了20分钟题看懂题意是个模拟,交了一发13分,想不出来测试点,于是看第二题,看样例以为直接用队列就行了,沉下心看题目,结果要按题意双栈模拟队列,调试了20分钟AC了,第三题常规的建树,求每个节点的度,调试20分钟AC了,这时一看排名33。就接着看第四题,看样例和题意都没看懂,这时还有1个半小时结束,后面又排序骗了5分,最后又回去想第一题的测试点,测不出来。一个半小时坐牢,就这样结束了这次考试。
赛后又补了下题,找队友一起读题读懂了A4, 还没测,以下代码是都是凭记忆写的,等过两天可以测题了,会再更新。
2023.6.11:已补完A1, A4题目,以下为AC代码。
A-1 Trap
A robot is designed to move on a map from South toward North. When some obstacle is encountered, the robot can only turn toward West and moves until it can turn toward North and continue.
Given a squared map with n×n blocks, a robot can start from any position below the bottom line (South) and its target is to reach the top line (North). (By the way, kindly remind you that the left-hand-side of the map is West and the right-hand-side is East.)
If some obstacles are placed in the map, the robot might get trapped if it starts from certain positions and can never reach the North line. For example, in the situation given by the following figure, the robot will be trapped if it starts from either position 7 or 8.
Your job is to point out those starting positions which will get the robot trapped.
Note: it is assumed that a robot can move out of the map boundary, and all the blocks around the map are open, without any obstacle. Hence if the robot starts from any position out of the West or East boundary, it can certainly reach North without any problem. Therefore we only have to consider the positions between the West and East boundaries (e.g. the positions from 1 to 10 below the South line in the above figure). Besides, as long as the robot can reach the North line, it is considered successful even of it ends up at out of the boundary (e.g. the robot will have to move out of the map if starts from either the positions 1 or 2, but it can still reach the North line).
Input Specification:
Each input file contains one test case. Each case starts from a positive integer n (≤100) in a line, which is the size of the map. Then n lines follow, each contains n characters, which are either 0
for an open block, or 1
for a block with obstacle. The first line corresponds to the North boundary and the last line the South.
Output Specification:
Output in a line all the starting positions which can get the robot trapped, in increasing order. The positions are indexed from West to East, starting from 1. It is guaranteed that there is at least one output.
All the numbers must be separated by 1 space, and there must be no extra space at the beginning or the end of the line.
Sample Input:
10
0000000000
0000111010
1100100011
0000110001
0000000011
0000000000
0100000100
0001000000
0001000000
0001100000
Sample Output:
7 8
题意:
给定一个N*N的地图,地图上有障碍物,规定从最后一行走,即最后一行列为1~n的为起点,可以先一直往上走,遇到障碍物后往左试探走一步再往上走,若再遇到障碍物,反复这样做。求不能走出地图的起点。
思路:
模拟,枚举每个起点即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e2 + 7;
int n;
vector<int> ans;
int g[N][N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%1d", &g[i][j]);
}
}
for (int j = 1; j <= n; j++) {
// int x = n + 1, y = j;
// while (g[x][j] == 0 && x >= 1) x --;
// while (g[x + 1][y] == 0 && y >= 1) y --;
// if (y != 0) ans.push_back(j);
int x = n + 1, int y = j;
while (x != 0) {
if (g[x - 1][y] == 0) {
x--;
} else if (g[x][y - 1] == 0) {
y--;
} else {
ans.push_back(j);
break;
}
}
}
for (int i = 0; i < (int)ans.size(); i++) {
if (i) printf(" ");
printf("%d", ans[i]);
}
return 0;
}
A-2 Queue Using Two Stacks
A queue (FIFO structure) can be implemented by two stacks (LIFO structure) in the following way:
- Start from two empty stacks s1 and s2.
- When element e is enqueued, it is actually pushed onto s1.
- When we are supposed to dequeue, s2 is checked first. If s2 is empty, everything in s1 will be transferred to s2 by popping from s1 and immediately pushing onto s2. Then we just pop from s2 -- the top element of s2 must be the first one to enter s1 thus is the first element that was enqueued.
Assume that each operation of push or pop takes 1 unit of time. You job is to tell the time taken for each dequeue.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤103), which are the number of operations. Then N lines follow, each gives an operation in the format
Operation Element
where Operation
being I
represents enqueue and O
represents dequeue. For each I
, Element
is a positive integer that is no more than 106. No Element
is given for O
operations.
It is guaranteed that there is at least one O
operation.
Output Specification:
For each dequeue operation, print in a line the dequeued element and the unites of time taken to do this dequeue. The numbers in a line must be separated by 1 space, and there must be no extra space at the beginning or the end of the line.
In case that the queue is empty when dequeue is called, output in a line ERROR
instead.
Sample Input:
10
I 20
I 32
O
I 11
O
O
O
I 100
I 66
O
Sample Output:
20 5
32 1
11 3
ERROR
100 5
题意:
给你两个栈,模拟一个队列,并且给出每次deque操作的时间。
AC代码:
#include <bits/stdc++.h>
#define all(s) s.begin(), s.end()
using namespace std;
const int N = 1e5 + 7;
string op;
int n, x, k;
stack<int> s1, s2;
int main() {
cin.tie(nullptr)->ios::sync_with_stdio(false);
cin >> n;
while (n -- ) {
cin >> op;
if (op == "I") {
cin >> x;
s1.push(x);
} else {
if (s1.empty() && s2.empty()) {
cout << "ERROR\n";
continue;
}
if (s2.empty()) {
while (!s1.empty()) {
s2.push(s1.top());
s1.pop();
k += 2;
}
}
cout << s2.top() << ' ' << ++ k << endl;
k = 0;
s2.pop();
}
}
return 0;
}
A-3 Rank of Binary Tree
Here we define the rank of a binary tree as n1×n2/n0 where ni is the number of nodes of degree i for i=0,1,2.
For example, given a tree shown by the figure, its rank is 2×3/4=1.5.
Given the inorder and preorder traversal sequences of a binary tree, you are supposed to calculate its rank.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤20), which is the total number of nodes in the tree. Then given in the following 2 lines are the inorder and preorder traversal sequences of the tree, respectively. All the keys in the tree are distinct positive integers in the range of int.
Output Specification:
For each case, print in a line the way we calculate the rank, and the integer part of the rank. The format is:
n1 * n2 / n0 = rank
Sample Input:
9
2 3 1 5 4 7 8 6 9
1 2 3 6 7 4 5 8 9
Sample Output:
2 * 3 / 4 = 1
题意:
给你一颗二叉树的先序遍历和中序遍历,求每个顶点的度。
思路:
递归建树,再进行从根节点dfs计算每个节点的度,注意节点范围在int,因此最好开个map。
#include <bits/stdc++.h>
using namespace std;
const int N = 20 + 7;
int n;
int inOrder[N], preOrder[N];
unordered_map<int, int> mp, degree;
struct TreeNode {
int val;
TreeNode *left, *right;
TreeNode(int x): val(x), left(nullptr), right(nullptr) {}
};
TreeNode *build(int inL, int inR, int preL, int preR) {
if (inL > inR) return nullptr;
int curRoot = preOrder[preL];
auto *root = new TreeNode(curRoot);
int k = mp[curRoot];
root->left = build(inL, k - 1, preL + 1, preL + k - inL);
root->right = build(k + 1, inR, preL + k - inL + 1, preR);
return root;
}
void DFS(TreeNode *root) {
if (!root) return ;
if (root->left) {
degree[root->val] ++;
DFS(root->left);
}
if (root->right) {
degree[root->val] ++;
DFS(root->right);
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> inOrder[i], mp[inOrder[i]] = i;
for (int i = 1; i <= n; i++) cin >> preOrder[i];
TreeNode *root = build(1, n, 1, n);
DFS(root);
int n0 = 0, n1 = 0, n2 = 0;
for (auto [k ,v] : mp) {
if (degree[k] == 0) n0 ++;
if (degree[k] == 1) n1 ++;
if (degree[k] == 2) n2 ++;
}
cout << n1 << " * " << n2 << " / " << n0 << " = " << (int)(n1 * 1.0 * n2 / n0);
return 0;
}
A-4 Big Number
How to generate a big number of N digits randomly? One way is to find N kids, give each one a card with one's index written on one side (hence it is assumed that the kids are indexed from 1 to N), and ask them to write down a 1-digit number randomly on the other side. Then let the kids pin their digits in a line, on the wall, one by one in ascending order of their indices.
However, it's very difficult to let hundreds of thousands of kids to follow the order. The result is that we have cards pinned randomly all over the wall, some even show the wrong sides. For example, if the 23rd kid has written down 8, we are supposed to find the number 8 on the wall. But instead we might find 23... Your job is to rearrange these cards so that we can obtain the big number as required.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤105). Then N lines follow, each describes a card in the format n1 n2
where the two numbers are the numbers written on the two sides of a card.
Output Specification:
For each test case, print in a line the N-digit number as required. That is, print the digits written by the kids in ascending order of their indices. In case that there are 1-digit numbers written on both sides, it would be hard to tell which one is the index and which one is the number written by the kid. Hence the solution may not be unique. In this case, just output the smallest resulting number.
It is guaranteed that a solution exists.
Sample Input:
12
7 11
8 9
3 1
2 12
4 6
10 0
5 1
2 5
6 8
1 4
7 2
9 3
Sample Output:
359114268072
这题当时考场上读了1小时没读懂题目,赛后问队友才明白题意。
题意:
给你n张卡牌,卡牌的一面写着索引(1-n)一面写着一位数的数字,这意味着若卡牌的一面为大于等于10的数字,则这个卡牌的索引和数字是确定的,若两面都为小于10的数字,则两面都可以互用,要求你按照索引给出最后拼成的最小的数字。
思路:
索引为10~n的数字是确定的,那么我们只考虑索引为1~9的即可,对于每个索引为1~9的我们找出当前可以放置的数字最小的,然后再把用过的这个边删掉即可。(这样的思路是错误的,这样贪心着放置数字可能会出现不合法的情况,例如当前位置选了当前最优的,删除后导致后面的索引没有数字可选了,也就是测试点2,3会报段错误)
(26分)
#include <bits/stdc++.h>
#define all(s) s.begin(), s.end()
using namespace std;
const int N = 1e5 + 7;
int n, a, b;
vector<int> g[N];
int main() {
cin.tie(nullptr)->ios::sync_with_stdio(false);
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a >> b;
if (a >= 10) swap(a, b); //索引是 y 数字是x
if (a < 10 && b < 10) {
g[a].push_back(b), g[b].push_back(a);
} else if (a < 10 && b >= 10) {
g[b].push_back(a);
}
}
for (int i = 1; i <= n; i++) {
if (i >= 10) cout << g[i][0];
else {
int minv = *min_element(all(g[i]));
g[minv].erase(find(all(g[minv]), i));
cout << minv;
}
}
return 0;
}
正解:
爆搜出所有合法的序列中的最优解。
AC代码
#include<bits/stdc++.h>
using namespace std;
vector <pair<int, int>> rec;
int n;
vector<int> getN(10, 0);
vector<int> ans0;
vector<int> temp;
bool greaterThan(vector<int> &a, vector<int> &b) {
for (int i = 1; i < a.size(); i++) {
if (a[i] != b[i]) {
return a[i] > b[i];
}
}
return false;
}
void dfs(int i) {
if (i == rec.size()) {
if (count(getN.begin() + 1, getN.begin() + rec.size() + 1, 0) == 0) {
for (int j = 0; j < rec.size(); j++) {
temp[rec[j].first] = rec[j].second;
}
if (ans0.size() == 0 || greaterThan(ans0, temp)) {
ans0 = temp;
}
}
} else {
getN[rec[i].first]++;
dfs(i + 1);
getN[rec[i].first]--;
swap(rec[i].first, rec[i].second);
getN[rec[i].first]++;
dfs(i + 1);
getN[rec[i].first]--;
}
}
int main() {
cin >> n;
vector<int> ans(n + 1, -1);
for (int i = 0; i < n; i++) {
int t1, t2;
cin >> t1 >> t2;
if (t1 < 10 && t2 < 10) {
rec.emplace_back(t1, t2);
} else {
ans[max(t1, t2)] = min(t1, t2);
}
}
temp.resize(rec.size() + 1);
dfs(0);
for (int i = 1; i < ans0.size(); i++) {
ans[i] = ans0[i];
}
for (int i = 1; i < ans.size(); i++) {
cout << ans[i];
}
return 0;
}