栈
PAT1051
梦回编译原理实验
#include <iostream>
#include <stack>
using namespace std;
int main() {
int M, N, K; // 栈的容量,序列大小,序列数
stack<int> s;
int n1;
int flag;
cin >> M >> N >> K;
int n2[N];
for (int i = 0; i < K; i++) {
n1 = 1;
flag = 1;
int j = 0;
for (int j = 0; j < N; j++) {
cin >> n2[j];
}
while (j < N) {
if (!s.empty() && s.top() == n2[j]) {
s.pop();
j++;
} else if ((n1 <= n2[j]) && (s.size() < M)) {
s.push(n1);
n1++;
} else {
flag = 0;
break;
}
}
if (flag == 1) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
while (!s.empty()) {
s.pop();
}
}
}
队列
PAT1056
最看不懂题目的一集。。完全抄的晴神的《上机训练》。
#include <iostream>
#include <queue>
#include <cmath>
#define MAXN 1010
using namespace std;
// 重量和排名绑在一起,这样就不用考虑对应的关系了
struct mouse {
int weight; // 重量
int rank; // 排名
}mouse[MAXN];
int main () {
int Np, Ng; // 编程者的数量,一组中老鼠数量的最大数
cin >> Np >> Ng;
queue<int> q;
for (int i = 0; i < Np; i++) {
cin >> mouse[i].weight;
}
int idx;
for (int i = 0; i < Np; i++) {
cin >> idx;
q.push(idx); // 只需要压入老鼠的顺序即可
}
double count; // 记录当前轮数有多少只老鼠
int groups; // 记录当前轮数的老鼠组数
int maxW;
int maxIdx;
while (q.size() > 1) {
count = q.size();
groups = ceil(count * 1.0 / Ng);
// cout << count << " " << groups << " ";
for (int i = 0; i < groups; i++) { // 当前轮
maxW = -1;
for (int j = 0; j < Ng; j++) { // 当前组
if (count > 0) { // 最后一组老鼠数量可能不满Np
idx = q.front();
// 每轮未晋级的老鼠排名相同,根据样例看,没有第四名老鼠,因此可以推断(好怪-。-):
// 每组晋级一只老鼠,当前轮晋级老鼠数等于组数,因此此轮未晋级的老鼠排名为group+1
mouse[idx].rank = groups + 1;
q.pop();
if (maxW < mouse[idx].weight) { // 选出最大的作为赢家
maxIdx = idx;
maxW = mouse[idx].weight;
}
count --;
}
}
q.push(maxIdx);
}
}
mouse[q.front()].rank = 1;
for (int i = 0; i < Np; i++) {
cout << mouse[i].rank;
if (i != Np - 1) cout << " ";
}
}
链表
PAT1074
一开始脑洞奇怪写了这个↓完全用链表的思想写的,很麻烦,得分22/25,最后两个一个段错误,一个超时。没有正确理解addr,addr可以是数组下标,所以正确方法应该是开一个100000>的数组。
以及这道题的坑点在于,有些节点可能是无效结点,比如:
00000 6 3
00000 1 11111
11111 2 22222
22222 3 -1
33333 4 44444
44444 5 55555
55555 6 -1
到结点三就输入完毕了,后面的4 5 6是无效结点
#include <iostream>
#include <string>
using namespace std;
struct node {
int data;
string addr;
string next;
int nextIdx;
};
int main() {
int N, K; // 结点数量,需要反转的结点数量
string head;
int headIdx;
cin >> head >> N >> K;
node list[N];
int num = N; // 有效结点数量
for (int i = 0; i < N; i++) {
cin >> list[i].addr >> list[i].data >> list[i].next;
if (head == list[i].addr) headIdx = i;
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (list[i].next == list[j].addr) {
list[i].nextIdx = j;
}
}
}
// 倒转链表
int t, p = headIdx, q = headIdx, h = headIdx; // p指当前结点,q指当前倒转链表的最后一个结点
int count = N / K;
for (int i = 0; i < count; i++) {
for (int j = 0; j < K - 1; j++) {
p = list[q].nextIdx;
list[q].nextIdx = list[p].nextIdx;
list[q].next = list[p].next;
list[p].nextIdx = h;
list[p].next = list[h].addr;
h = p;
}
if (i == 0) {
headIdx = h;
}
else {
list[t].next = list[h].addr;
list[t].nextIdx = h;
}
if (list[q].next == "-1") {
num = (i + 1) * K;
break;
}
t = q;
h = list[q].nextIdx;
q = h;
p = h;
}
int idx = headIdx;
for (int i = 0; i < num; i++) {
cout << list[idx].addr << " " << list[idx].data << " " << list[idx].next << endl;
idx = list[idx].nextIdx;
}
}
看了网上的还有这个简单的↓,使用reverse,虽然我感觉这已经不是链表的思想了。启发是有些链表的题用数组模式存储可以简化实现。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct node {
int data;
int next;
}list[100010];
int main() {
int head, N, K; // 结点数量,需要反转的结点数量
list[100010];
cin >> head >> N >> K;
int addr;
for (int i = 0; i < N; i++) {
cin >> addr >> list[addr].data >> list[addr].next;
}
// 存地址
vector<int> v;
for (int i = head; i != -1; i = list[i].next) {
v.push_back(i);
}
// 逆序
for (int i = 0; i < v.size() / K; i++) {
reverse(v.begin() + K * i, v.begin() + K * (i + 1));
}
for (int i = 0; i < v.size(); i++) {
printf("%05d %d ", v[i], list[v[i]].data);
if (i == v.size() - 1) printf("-1");
else printf("%05d\n", v[i+1]);
}
}
PAT1032
这题好简单,开心一秒,畅想考试的时候遇到这么简单的(
#include <iostream>
#include <string>
#define MAXV 100010
using namespace std;
struct node {
string data;
int next;
}list[MAXV];
int main() {
int h1, h2, N;
cin >> h1 >> h2 >> N;
int idx;
for (int i = 0; i < N; i++) {
cin >> idx >> list[idx].data >> list[idx].next;
}
int len1 = 0, len2 = 0;
for (int i = h1; i != -1; i = list[i].next) {
len1++;
}
for (int i = h2; i != -1; i = list[i].next) {
len2++;
}
int p = h1, q = h2;
while (p != -1 && q != -1) {
if (p == q) {
printf("%05d", p);
return 0;
}
if (len1 > len2) {
len1 --;
p = list[p].next;
} else if (len1 < len2) {
len2 --;
q = list[q].next;
} else {
p = list[p].next;
q = list[q].next;
}
}
printf("-1");
}
PAT1052
这题也很简单,就是无效结点不讲武德= =
#include <iostream>
#include <vector>
#include <algorithm>
#define MAXV 100000
using namespace std;
struct node {
int data;
int next;
int addr;
} list[MAXV];
bool cmp (node n1, node n2) {
return n1.data < n2.data;
}
int main() {
int N, h;
cin >> N >> h;
int addr;
for (int i = 0; i < N; i++) {
cin >> addr >> list[addr].data >> list[addr].next;
list[addr].addr = addr;
}
vector<node> v;
node n;
for (int i = h; i != -1; i = list[i].next) {
v.push_back(list[i]);
}
if (v.size() == 0) { // 无效结点,好坑= =
printf("0 -1");
return 0;
}
sort(v.begin(), v.end(), cmp);
printf("%d %05d\n", v.size(), v[0].addr);
for (int i = 0; i < v.size(); i++) {
printf("%05d %d ", v[i].addr, v[i].data);
if (i == v.size() - 1) printf("-1");
else printf("%05d\n", v[i+1].addr);
}
}
PAT1097
空间换时间,而且简化代码
#include <iostream>
#include <vector>
#include <cmath>
#define MAXV 100010
#define MAX 10010
using namespace std;
struct node {
int key;
int next;
} list[MAXV];
int main () {
int h, N;
cin >> h >> N;
int addr;
for (int i = 0; i < N; i++) {
cin >> addr >> list[addr].key >> list[addr].next;
}
vector<int> v1;
vector<int> v2;
int flag[MAX] = {0};
for (int i = h; i != -1; i = list[i].next) {
if (flag[abs(list[i].key)]) {
v2.push_back(i);
} else {
v1.push_back(i);
flag[abs(list[i].key)] = 1;
}
}
for (int i = 0; i < v1.size(); i++) {
printf("%05d %d ", v1[i], list[v1[i]].key);
if (i == v1.size() - 1) printf("-1\n");
else printf("%05d\n", v1[i+1]);
}
for (int i = 0; i < v2.size(); i++) {
printf("%05d %d ", v2[i], list[v2[i]].key);
if (i == v2.size() - 1) printf("-1\n");
else printf("%05d\n", v2[i+1]);
}
}